6

Is it possible in Django Rest Framework to add a HyperLink on the id field of each record in the ModelViewSet List View that links to the Detail View for that record?

The documentation says to add a view_name argument, but is this possible to do under a ModelViewSet because the views don't actually have names?

2 Answers 2

13

first thing is that ALL ModelViewSet urls have names, even if you don´t set those names explicitly.

You can find out how the default urls are created within a router, in the docs: http://www.django-rest-framework.org/api-guide/routers/ (see 'SimpleRouter' url names table)

To see all the actual url names available in your application, try with this utility:

def print_url_pattern_names(patterns):
    """Print a list of urlpattern and their names"""
    for pat in patterns:
        if pat.__class__.__name__ == 'RegexURLResolver':            # load patterns from this RegexURLResolver
            print_url_pattern_names(pat.url_patterns)
        elif pat.__class__.__name__ == 'RegexURLPattern':           # load name from this RegexURLPattern
            if pat.name is not None:
                print '[API-URL] {} \t\t\t-> {}'.format(pat.name, pat.regex.pattern)

Then, in your urls.py:

urlpatterns = [
    url(r'^', include(router.urls)),
]

if settings.DEBUG:
    print_url_pattern_names(urlpatterns)

If you want the url to be different from your ModelViewSet´s name (as in my case) you can set it on the router with "base_name":

router.register('contents', media_views.MediaViewSet, base_name='contents')

Next thing you´ll need is extending HyperlinkedModelSerializer:

from rest_framework import serializers
# in this sample my object is of type "Media"
class MediaSerializer(serializers.HyperlinkedModelSerializer):
    #blablabla

You will have a serializer ready to show hyperlinks to your detail view, but there is one required step left for this to work. That´s where the "view_name" comes in:

from rest_framework import serializers
class MediaSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Media
        fields = ('url', ...[other fields you want to serialize])
        extra_kwargs = {
            'url': {'view_name': 'contents-detail'}
        }
  1. 'url' field is mandatory to show the link.
  2. With 'extra_kwargs' > view_name you´re telling the framework that your detail view´s name is 'content-detail'.
  3. 'content-detail' is just MY view´s name. You need to find out yours (from the url names utility above)

And this is the http response from the sample (see url field):

enter image description here

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

3 Comments

here you are setting 'contents-detail' as the url name. Do you need to declare this url in the urls.py?
No. As I mentioned, the router/modelViewSet will create urls for you: django-rest-framework.org/api-guide/routers. But in my particular case, given that I want the url to start with "content" rather than "media", I set that on the urls.py (edited the post)
I removed the extra_kwargs for the view_name because it isn't needed in a HyperlinkedModelSerializer and it worked. Also, this answer helped me get it working: stackoverflow.com/a/20553926/1913888. I still put +1 for your answer. Thank you.
2

Little update to xleon's answer:

With Python 3 and new Django, function to see all urlpatterns you should use something like this:

def print_url_pattern_names(patterns):
    """Print a list of urlpattern and their names"""
    for pat in patterns:
        if pat.__class__.__name__ == 'URLResolver':      # load patterns from this URLResolver
            print_url_pattern_names(pat.url_patterns)
        elif pat.__class__.__name__ == 'URLPattern':     # load name from this URLPattern
            if pat.name is not None:
                print('[API-URL] {:>50} -> {}'.format(pat.name, pat.pattern))

I spent some time resolving it, so maybe it will help somebody.

How I used it: run "python manage.py shell", then

import urls

then copy this function and run it like this:

print_url_pattern_names(urls.urlpatterns)

Comments

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.