In this blog post we will see more details on View Class and also router.
Read this https://www.django-rest-framework.org/api-guide/routers/ to understand routers briefly.
In our previous blog post we saw simple routes with regex. DRF router can be used that as well with simple regex and its quite power. Here are few blogs which show different useful regex and many can be found online as well
Let’s take the first route shown in above blog as an example in our code base
url(r'^(?P<pk>\d+)/$', views.index, name='test_regex'),
and our function would look like
@api_view() def index(request, pk): todo = Todo.objects.get(pk=pk) ser = TodoSerializer(todo) return Response(ser.data)
Take note how we are passing ‘pk’ dynamic variable from route to function. This is quite simple and can be extended as required
Simple RouteR and View Sets
DRF has a concept of “simple router”. This is to be used with ViewSets only and mainly reason for this it generate lot of routes automatically based on the ViewSets.
Before going into detail let’s recap what we have seen till now because this can be a bit confusing
a) @api_view: this is simple function based view and can be paired with regex based routing. By default it’s GET type but we can add more types easily. This suppose decorators for permission, authentication, etc etc https://www.django-rest-framework.org/api-guide/views/#function-based-views
b) ViewClass (APIView): this is a class based view with methods for “get”, “post” “list” “delete” etc. This can be paired with regex based routing and also suppose decorates for auth, permission etc https://www.django-rest-framework.org/api-guide/views/#class-based-views
c) Generic Views : this is extension of APIView and provides default features on top of it.
The above view method’s are quite flexible and can be easily paired with routes using regex.
Pros: Easy to use and implement. Easy to understand
Cons: No fixed structure, this will cause problem in large projects as every developer will make things on this own. No code consistency will be there.
View sets are similar to Generic Views, except that are paired with “SimpleRouter” and hence provide a consistent interface for routing and code structure.
Let’s see how this works
There are all the different actions a viewset provides by default
def list(self, request): pass def create(self, request): pass def retrieve(self, request, pk=None): pass def update(self, request, pk=None): pass def partial_update(self, request, pk=None): pass def destroy(self, request, pk=None): pass
Let’s see this at code level
//todo/views.py from todo.models import Todo from todo.serializers import TodoSerializer from rest_framework import viewsets class TodoViewSet(viewsets.ModelViewSet): serializer_class = TodoSerializer queryset = Todo.objects.all() //todo/urls.py from rest_framework.routers import DefaultRouter from todo.views import TodoViewSet router = DefaultRouter() router.register(r'todo', TodoViewSet, basename='todo') urlpatterns = router.urls
We are using “ModelViewSet” because this implement all functions i.e create, delete, list, etc by default. If you use instead “ViewSet” it won’t have any of the functions implemented.
To see this open postman and fire all the route GET, POST, PUT, etc and all will work
So basically with just a few lines of code we are able to setup full CRUD operations
Read in detail simple router and default router to understand there difference between them and what kind of routes they generate automatically
Actions are also quite important in viewset. Basically suppose we want to add an extra function to viewset which is out of the standard CRUD. It done via action.
Read more about actions here the explanation is quite clear how to use it https://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing
Read about different view sets here as well https://www.django-rest-framework.org/api-guide/viewsets/#api-reference