[Fixed]-DRF – using view classes for custom URL design?

1πŸ‘

I realise this is a little late but incase anyone else finds this:

viewset.py:

class UserViewSet(RetrieveModelMixin, UpdateModelMixin, GenericViewSet):
    queryset = None
    serializer_class = serializers.UserSerializer

    def get_object(self):
        return self.request.user

This isn’t a full example for the one above but is a good example. Here get_object doesn’t rely on a queryset, but can still provide an object without a pk.

urls.py:

urlpatterns = [
    # GET:  /user/ [Retrieve]
    # PUT:  /user/ [Update]
    url(
        r'^user/$',
        UserViewSet.as_view({'get': 'retrieve', 'put': 'update'}),
        name='user'
    ),
]

Here, instead of relying on the drf router to provide the urls (which automatically include a pk object), the routes are defined in the standard Django format. This allows for the removal of a detail pk (or the addition of an optional one etc).

πŸ‘€Darkstarone

0πŸ‘

Basically, you can make a view subclass generics.GenericAPIView, and add mixins for CURD like the following codes:

urls.py

url(r'^/user/(?P<pk>\d+)/detail/$', UserDetailView.as_view(), name='user_detail'),
url(r'^/user/(?P<pk>\d+)/update/$', UserDetailView.as_view(), name='user_update'),
url(r'^/user/list/$', UserListView.as_view(), name='user_list'),

views.py

from rest_framework import mixins
from rest_framework import generics

class UserListView(mixins.ListModelMixin,
                   generics.GenericAPIView):
    queryset = MyUser.objects.all()
    serializer_class = UserSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

class UserDetailView(mixins.RetrieveModelMixin,
                     mixins.UpdateModelMixin,
                     mixins.DestroyModelMixin,
                     generics.GenericAPIView):
    queryset = MyUser.objects.all()
    serializer_class = UserSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def patch(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)

If you need more control on the logic, you can:

  1. [User List]: override the get_queryset in UserListView, and supply your logic to filter users and return the queryset.
  2. [Get user detail]: same as above, but override get_queryset in UserDetailView
  3. [Patch user]: override partial_update in UserDetailView to supply your logic for updating.

In a word, mixins is the good place for you to start to create more generic class-based views on DRF.

πŸ‘€Enix

Leave a comment