6

I'm wondering if there is a clean way to retrieve an object from its URL with django rest framework. Surely there should be, as it seems to be what's happening when using HyperlinkedRelatedField.

For instance, I have this URL /api/comment/26 as a string. From my view, how can I get the comment instance with pk=26?

Of course I could redo the work and work on the string but it must be a better way?

Thanks a lot.

EDIT:

This is how I solved it at the end:

resolve('/api/comment/26/').func.cls.model will return my model Comment. resolve('/api/category/1/').kwargs['pk'] will return the pk.

Which gives you:

from django.core.urlresolvers import resolve

resolved_func, unused_args, resolved_kwargs = resolve('/api/category/1/')
resolved_func.cls.model.objects.get(pk=resolved_kwargs['pk'])
3
  • Remember that if you have a fully qualified URL (e.g. starting with "http...") you need to extract its path and pass that to resolve. This can be done with the urlparse module. Commented Jul 6, 2015 at 18:52
  • 1
    I didn't look into it to much but for me resolved_func.cls returns the view set so I needed to use the following to get to the model: resolved_func.cls.serializer_class.Meta.model.objects.get(pk=resolved_kwargs['pk']) Commented Nov 24, 2015 at 1:32
  • This is not working with django 2.1 and python 3.5 anymore Commented Sep 11, 2019 at 16:59

3 Answers 3

3

I suspect your best bet would be to manually keep a map of models to url patterns — not too dissimilar from a URLConf.

If that doesn't rock your boat you could pass the path into resolve.

This will give you a ResolverMatch upon which you'll find the func that was returned by the as_view call when you set up your URLs.

The __name__ attribute of your view function will be that of your original view class. Do something like globals()[class_name] to get the class itself.

From there access the model attribute.

I hope that helps. As I say, you might just want to map models to URLs yourself.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your help!!! Nearly there, I tweaked a bit your answer to get exactly want I needed that way: resolve('/api/category/1/').func.cls.model
Ah, ...func.cls is there is it? — Never needed it but that's much cleaner. Thank you to you too!
2

With class-based views, something like the following seems needed:

resolve(url).func.cls.serializer_class.Meta.model.objects.get(
    **resolve(url).kwargs)

Comments

0

Solution above did not work for me, the following did work though:

from django.core.urlresolvers import resolve

resolved_func, unused_args, resolved_kwargs = resolve('/api/category/1/')
resolved_func.cls().get_queryset().get(id=resolved_kwargs['pk'])

additionally this solution uses the built in queryset of your view, which might have annotations or important filters.

Using HyperlinkedModelSerializer I actually needed to do this with a full url. For this to work, you need to extract the path first, resulting in:

import urllib.parse
from django.core.urlresolvers import resolve

def obj_from_url(url):
    path = urllib.parse.urlparse(url).path
    resolved_func, unused_args, resolved_kwargs = resolve(path)
    return resolved_func.cls().get_queryset().get(id=resolved_kwargs['pk'])

1 Comment

django.core.urlresolvers module has been removed in Django 2.0 and url-related functions (like resolve) has been moved to django.urls: docs.djangoproject.com/en/3.0/ref/urlresolvers/#resolve

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.