Django rest framework from beginner to advance
By datnq, at: 17:03 Ngày 19 tháng 12 năm 2023
Django rest framework from beginner to advanced
We'll kick off with the fundamentals of RESTful APIs, acquaint ourselves with serializers, authentication, and ultimately delve into challenging advanced topics. With practical insights and specific examples, this article promises to provide you with a rich learning experience, helping you master Django Rest Framework step by step. Begin your adventure from beginner to advanced today!
1. How to create a basic api, running stream
The main components of a basic api in drf include 2 parts: serializer and view. After importing the library and setting everything up successfully, let's say you want to create a basic api with the GET method to retrieve all data about books. With serializers:
from app.models import Book
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['name', 'author', 'rate']
DRF's serializer to support serializing and deserializing from Python code to JSON. Here UserSerializer will return API results containing the field name, author, rate
View in DRF is a way to access the API through properties.
from app.models import Book
from rest_framework import permissions, viewsets
from app.serializers import BookSerializer
class UserViewSet(viewsets.ModelViewSet):
serializer_class = BookSerializer
permission_classes = [permissions.IsAuthenticated]
With a simple view, DRF has created an API that returns book data according to the BookSerializer above. The permission_classes attribute is declared to require user authentication if you want the API to execute.
2. Custom fields, validate in serializer
In addition to using the fields in the model, users can also return API results based on self-created fields.
class BookSerializer(serializers.ModelSerializer):
date_publish = serializers.SerializerMethodField()
class Meta:
model = Message
fields = ['name', 'author', 'rate', 'date_publish']
def get_date_publish(self, obj):
"""
logic code for result of date publish
"""
With a simple view, DRF created an API that responds to book data according to the BookSerializer above. The allow_classes attribute declares a target that requires the target to be authenticated by the user if it wants the API to execute.
3. Customize fields, validation in serializer
In addition to using fields available in the model, users can also return API results based on automatically generated fields.
class BookSerializer(serializers.ModelSerializer):
date_publish = serializers.SerializerMethodField()
class Meta:
model = Message
fields = ['name', 'author', 'rate', 'date_publish']
def get_date_publish(self, obj):
"""
logic code for result of date publish
"""
For each data book, date_publish has the same value as any dependent values returned by the get_date_publish function.
Besides, we also have to validate whether the ratio has a reasonable value or not. DRF also supports this. For a simple example, calculating the value of a book requires a value greater than 0 and less than 5. It is necessary to add a function to check the return value ratio for the BookSerializer class.
def validate_rate(self, value):
if value < 0 or value > 5:
raise serializers.ValidationError("Error")
return value
DRF strongly supports serializers, giving users flexibility in creating serializers at their discretion.
4. Views Comparison
When it comes to views and views newbies will have quite a bit of freedom in their work, to choose the right type of API to use. Below is a comparison table drawn for easier observation.
View type | Use cases |
function view | It is a basic type of view, easy to create and easy to understand. However, because it does not follow any rules, it is difficult to maintain the code later, limiting its use. |
class APIView | Has the same mechanism as function view, the improvement is that the class supports many attribute methods to serve requests, is easier to maintain, and supports some more specific functions such as .get(), and .post(). However, there are still many limitations |
class GenericAPIView | One outstanding improvement of drf, GenericAPIView, I feel is a very good class to use to create API. The highlight that must be mentioned when using GenericAPIView is that it allows the use of query set, allows mapping to a separate serializer_class, ... and especially using mixins. This is reminiscent of Django's generic class-based view. In addition, we can simplify the API with concrete view classes (for example, if there is only 1 get API for the model, instead of using GenericAPIView, we can use ListAPIView) |
class ViewSet | Similar to the APIView class, however instead of the general function .get(), .post(), ViewSet specifies two methods: .list() and .create(). The strong point of viewsets is that they automatically declare the URL according to registration instead of creating the URL manually like the views above |
function GenericViewSet | Similar to GenericAPIView, supports automatically generating URL according to registration |
class ModelViewSet | Similar to GenericViewSet, supports automatic URL generation, with additional support for .list(), .retrieve(), .create(), .update(), .partial_update(), and .destroy() |
5. Custom Actions
As you know, viewset supports automatically generating urls:
from app.models import Book
from app.serializers import BookSerializer
from rest_framework import viewsets
class BookViewSet(viewsets.ViewSet):
def list(self, request):
queryset = Book.objects.all()
serializer = BookSerializer(queryset, many=True)
return Response(serializer.data)
Above is a simple example of ViewSet creating an API to retrieve all book data. To declare the endpoint for this API, simply add the following to urls.py:
router.register(r'books', BookViewSet, basename='book')
The above code helps automatically declare APIs in the BookViewSet class. In case you want to create a specific API as desired, DRF has an extra_action to help support this:
@action(detail=True, methods=["get"], name="Example")
def example(self, request, pk=None):
"""Logic code here"""
...
Now the user has an API/example of books with the GET method.
6. Using filter and custom permission, authentication
So everyone now has a better understanding of the framework, some ways to register an API, how to choose a suitable view, and design a serializer. For each API, there is always a filter and user authentication set. At the end of the article, I would like to leave some simple ways to create filters, permissions, and authentication depending on the requirements.
6.1. With filter:
You can use some special available filter backends such as:
- DjangoFilterBackEnd
- SearchFilter
- OrderingFilter
Additionally, you can learn about the third library 'django_filter' in case you want to create an advanced filter on demand.(https://django-filter.readthedocs.io/en/stable/guide/install.html)
6.2. With permission and authentication:
Override the BasePermission and BaseAuthentication functions to use as desired.
For example:
from rest_framework.permissions import BasePermission
class ExamplePermission(BasePermission):
def has_permission(self, request, view):
"""
write logic here, return True if successful, otherwise return False
"""
Conclusion
This guide has walked you through the fundamentals of Django Rest Framework, from setting up basic APIs to customizing serializers and understanding different view types. By following these steps and examples, you should now have a solid foundation in DRF, ready to tackle more advanced topics.
Stay tuned for Part 2, where we will dive deeper into advanced DRF features, including more complex serializers, custom authentication mechanisms, and performance optimization techniques. Keep learning and exploring!