2

I am stuck trying to work out how to create a Django REST Framework ViewSet.

The API calls I have inherited look like this:

/api/v1/user/<user_id>/like_count
/api/v1/user/<user_id>/friends/
/api/v1/user/login
/api/v1/user/logout/

In my base urls.py I have the following:

urlpatterns = patterns('',
    url(r'^api/v1/', include('api.urls')), 
    url(r'^$', TemplateView.as_view(template_name='base.html'), name='home'),
    url(r'^docs/', include('rest_framework_swagger.urls'))
)

I have an app called api. In the api urls.py I have:

from django.conf.urls import url, include
from rest_framework import routers
from api import views

router = routers.DefaultRouter()
router.register(r'user', views.UserViewSet) 

urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

In my api/views.py file I want to create a UserViewSet class that handles all the possible variants of the url calls.

First I can't work out if I should use:

class UserViewSet(viewsets.ModelViewSet):

or...

class UserViewSet(APIView):

If I understand it correctly I can cater for the

/api/v1/user/login
/api/v1/user/logout 

calls using something like:

class UserViewSet(viewsets.APIView):
    def login(self, request, format=None):
        ...
    def logout(self,request, format=None):

But I can't work out how to cater for the other variants that have the <user-id> in the url.

Is there a recommended way to do this?

Some API calls have a trailing '/' and some don't. It is what I have been given (to fit in with an existing mobile app).

EDIT: By the way, I have done the DRF tutorial twice now and still can't see how to do this.

EDIT2: I am really struggling to understand the DRF documentation for this. Can anyone provide some example code that deals with my use case?

5
  • Follow the tutorial on DRF's website. No kidding. Commented Sep 13, 2015 at 19:45
  • Yes indeed! I have done the tutorial twice now but am still failing to see how to do this. Hence this question on Stackoverflow. Commented Sep 13, 2015 at 20:12
  • Before you go off implementing custom URLs and stuff because nobody realized DRF can do this automatically, look in the docs for the decorators for viewsets which allow for custom routing and views. You're looking for two detail routes and two list routes. Commented Sep 14, 2015 at 12:14
  • @BillNoble login and logout are methods in UserViewsets endpoint. You cann't acess like that. Commented Sep 14, 2015 at 13:02
  • Someone has edited my question and changed it so it is no longer meaningful! Commented Sep 14, 2015 at 14:19

2 Answers 2

1

Using a ViewSet or Views will depend on what other actions you need for your user resource apart from those you have in your urls. ModelViewSet is built from mixins for listing, updating etc. You can combine those to achieve what you want or you can just go with a combination of views.

Of course you can combine a viewset with views if you have to.

For the /api/v1/user/<user_id>/friends/ endpoint you can look at DRF docs or at DRF Nested Routers.

The like_count can be implemented with a view that returns just that single value.

Auth is a different topic entirely --- you can look at this.

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

4 Comments

I have read the docs several times but cannot see how to create a viewset that handles all of the api calls i listed. Hence the reason I am asking here.
Do you really have to implement the whole thing with a single viewset?
I am open to suggestions but would like to understand how to use a single viewset if possible
I think using a nested router for friends still counts? You will have to fillter the queryset in your viewset to use it. For the like count you can look here and add a custom @detail_route on your viewset. I can't see any straightforward solution for auth though.
1

viewsets.py

class UserViewset(viewsets.ModelViewSet):
    lookup_field = 'id'
    serializer_class = UserSerializer
    queryset = User.objects.all()

urls.py

from .viewsets import UserViewSet
user_list = UserViewSet.as_view({'get':'list'})
user_detail = UserViewSet.as_view({'get':'retrieve'})

urlpatterns= [
    url(r'^user/(?P<id>\d+)/(?P<friends>[-\w\d]+)/$', user_detail, name='user-detail')

]

In the serializers.py adde the ParameterisedHyperlinkedIdentityField as a serializer.

serializers.py

class UserSerializer(serializers.HyperlinkedModelSerializer):
    url = ParameterisedHyperlinkedIdentityField(view_name='user-detail', lookup_fields=(('id', 'id'), ('friends', 'friends')), read_only=True)

    class Meta:
        model = User

3 Comments

It sounds like they already have the views set up, they are just trying to migrate them to a view set. So I have no idea how recommending a totally different auth system helps here.
I am not having problems with the auth stuff
That code is kinda what I already have. I am looking for an example of how to pickup in the UserViewSet parameters in the url such as <user-id>, <age> etc. I have read all the documentation I have been pointed at but still can't work out how to do this so what I need to see is a proper example.

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.