Django Rest Framework: Access item detail by slug instead of ID
You should set lookup_field
in your serializer:
class ItemSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Item
fields = ('url', 'slug', 'title', 'item_url')
lookup_field = 'slug'
extra_kwargs = {
'url': {'lookup_field': 'slug'}
}
and in your view:
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
lookup_field = 'slug'
I got this result:
~ curl http://127.0.0.1:8000/items/testslug/ | python -mjson.tool
{
"item_url": "https://example.com/",
"slug": "testslug",
"title": "Test Title",
"url": "http://127.0.0.1:8000/items/testslug/"
}
In some scenarios you may want to have both the "low level" pk
value and the more semantic slug
. I like to have both options personally and do this by setting the lookup_field
later in the viewset as_view()
method in my urls.py
.
Note: the following defaults to
pk
with an optionalslug
lookup. To combine this with previous answer you would change thelookup_field
below to be"pk"
instead of"slug".
from django.conf.urls import *
from rest_framework.urlpatterns import format_suffix_patterns
from myobjects import views as myviews
# simplify the view definitions by splitting out the options
REQDICT = {
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
}
# define the pk detail view
myobject_detail = myviews.MyObjectViewset.as_view(REQDICT)
# define the slug detail view
myobject_slug_detail = myviews.MyObjectViewset.as_view(REQDICT, lookup_field='slug')
urlpatterns = [
url(r"^myobjects/(?P<pk>\d*)/$",
myobject_detail,
name = 'myobject-detail'),
url(r"^myobjects/(?P<slug>[-\w]+)/$",
myobject_slug_detail,
name = 'myobject-slug-detail'),
]
urlpatterns = format_suffix_patterns(urlpatterns)
This could also be in your
views.py
- my preference is to see it beside theurlpatterns
list.