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?
ModelViewSet. The ModelViewSet class inherits from GenericAPIView and includes implementations for various actions, by mixing in the behavior of the various mixin classes. The actions provided by the ModelViewSet class are .list() , .retrieve() , .create() , .update() , .partial_update() , and .destroy() .
A ViewSet is a class-based view, able to handle all of the basic HTTP requests: GET, POST, PUT, DELETE without hard coding any of the logic. The viewsets module also provides a ModelViewSet class that maps HTTP request actions to CRUD actions in the Database.
HyperlinkedModelSerializer is a layer of abstraction over the default serializer that allows to quickly create a serializer for a model in Django. Django REST Framework is a wrapper over default Django Framework, basically used to create APIs of various kinds.
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'}
}
And this is the http response from the sample (see url field):
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With