Skip to content

Commit

Permalink
Added viewssets docs
Browse files Browse the repository at this point in the history
  • Loading branch information
shabda committed Mar 14, 2018
1 parent 062fdc9 commit 57ed5b3
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 10 deletions.
64 changes: 63 additions & 1 deletion docs/more-views-and-viewsets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,66 @@ And for :code:`CreateVote`,
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
We pass on poll id and choice id. We subclss this from :code:`APIView`, rather than a generic view, because we competely customize the behaviour.
We pass on poll id and choice id. We subclss this from :code:`APIView`, rather than a generic view, because we competely customize the behaviour. This is similiar to our earlier :code:`APIView`, where in we are passing the data to a serializer, and savig or returnning an error depending on whether the serializer is valid.

Introducing Viewsets and Routers
-----------------------------------

Our urls are looking good, and we have a views with very little code duplication, but we can do better.

The :code:`/polls/` and :code:`/polls/<pk>/` urls require two view classes, with the same seralizer and base queryset. We can group them into a viewset, and connect the to the urls using a router.

This is what it will look like:

.. code-block:: python
# urls.py
# ...
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('polls', PollViewSet, base_name='polls')
urlpatterns = [
# ...
]
urlpatterns += router.urls
# views.py
# ...
from rest_framework import viewsets
from .models import Poll, Choice
from .serializers import PollSerializer, ChoiceSerializer, VoteSerializer
class PollViewSet(viewsets.ModelViewSet):
queryset = Poll.objects.all()
serializer_class = PollSerializer
There is no change at all to the urls or to the responses. You can verify this by doing a GET to
:code:`/polls/` and :code:`/polls/<pk>/`.


Choosing the base class to use
-----------------------------------

We have seen 4 ways to build API views until now

- Pure Django views
- :code:`APIView` subclasses
- :code:`generics.*` subclasses
- :code:`viewsets.ModelViewSet`

So which one should you use when? My rule of thumb is,

- Use code:`viewsets.ModelViewSet` when you are goin to allow all or most of crud operations on a model.
- Use :code:`generics.*` when you only want to allow some operations on a model
- Use :code:`APIView` when you want to completely customize the behaviour.

Next steps
-----------------

In the next chapter, we will look at adding access control to our apis.
8 changes: 2 additions & 6 deletions pollsapi/polls/apiviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@
from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response
from rest_framework import viewsets

from .models import Poll, Choice
from .serializers import PollSerializer, ChoiceSerializer, VoteSerializer


class PollList(generics.ListCreateAPIView):
queryset = Poll.objects.all()
serializer_class = PollSerializer


class PollDetail(generics.RetrieveDestroyAPIView):
class PollViewSet(viewsets.ModelViewSet):
queryset = Poll.objects.all()
serializer_class = PollSerializer

Expand Down
12 changes: 9 additions & 3 deletions pollsapi/polls/urls.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from django.urls import path

from .apiviews import PollList, PollDetail, ChoiceList, CreateVote
from .apiviews import PollViewSet, ChoiceList, CreateVote

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('polls', PollViewSet, base_name='polls')


urlpatterns = [
path("polls/", PollList.as_view(), name="polls_list"),
path("polls/<int:pk>/", PollDetail.as_view(), name="polls_detail"),
path("polls/<int:pk>/choices/", ChoiceList.as_view(), name="polls_list"),
path("polls/<int:pk>/choices/<int:choice_pk>/vote/", CreateVote.as_view(), name="polls_list"),

]

urlpatterns += router.urls

0 comments on commit 57ed5b3

Please sign in to comment.