I am trying to use the django rest framework to expose my models as APIs.
serializers
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
viewset
class UserViewSet(viewsets.ModelViewSet):
"""
API end point for User details and list
"""
serializer_class = UserSerializer
queryset = User.objects.all()
routers
router.register(r'users',views.UserViewSet)
While this exposes /users/ and users/, I want my URLs to include a user-slug as well, something like /users/1/xyz-user-name.
Has anyone solved this problem? Does this need changes in both the viewset and router code or is it something that can be configured only in the router code? MY "slug" isn't really used for determining url routing, it is only for URL readability.
Any pointers?
Custom exception handlingThe exception handler function should either return a Response object, or return None if the exception cannot be handled. If the handler returns None then the exception will be re-raised and Django will return a standard HTTP 500 'server error' response.
Django REST framework (DRF) is a powerful and flexible toolkit for building Web APIs. Its main benefit is that it makes serialization much easier. Django REST framework is based on Django's class-based views, so it's an excellent option if you're familiar with Django.
APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.
A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as .get() or .post() , and instead provides actions such as .list() and .create() .
I was able to get this to work by using the approach posted here.
django-rest-framework HyperlinkedIdentityField with multiple lookup args
The second error I was receiving was becuase I was including the url definition inside the meta section. It should be before the meta section instead. I also had to specify the lookup field in the viewset code. Here are the relevant parts of my code.
urls.py
from user.views import UserViewSet
user_list = UserViewSet.as_view({'get':'list'})
user_detail = UserViewSet.as_view({'get':'retrieve'})
urlpatterns= [
url(r'^users/$', user_list, name='user-list'),
url(r'^user/(?P<id>\d+)/(?P<slug>[-\w\d]+)/$', user_detail, name='user-detail'),
url(r'^api-auth/', include('rest_framework.urls',namespace = 'rest_framework'))
]
views.py:
class UserViewSet(viewsets.ModelViewSet):
"""
API end point for user details and user list
"""
lookup_field = 'id'
serializer_class = UserSerializer
queryset = user.objects.all()
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
url = ParameterisedHyperlinkedIdentityField(view_name='user-detail', lookup_fields=(('id', 'id'), ('slug', 'slug')), read_only=True)
class Meta:
model = user
fields = ('url','name','cover_photo')
You should set the lookup_field
property in the serializers and viewsets.
In the serializers.py:
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'email', 'user_slug')
lookup_field = 'user_slug'
extra_kwargs = {
'url': {'lookup_field': 'user_slug'}
}
In the viewsets.py:
class UserViewSet(viewsets.ModelViewSet):
serializer_class = UserSerializer
queryset = User.objects.all()
lookup_field = ('user_slug')
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