Django Rest Framework serialization component

Posted by robcrozier on Fri, 13 Dec 2019 17:54:49 +0100

drf serialization component

Basic use

  • urls.py
from django.urls import re_path
urlpatterns = [
    re_path(r'books/$', views.BookView.as_view()),
    re_path(r'books/(?P<pk>\d+)/$', views.BookFilterView.as_view()),
]
  • serialization class
from rest_framework import serializers

class BookSerializer(serializers.Serializer):
	title = serializers.CharField(max_length=32)
	# Foreign key field
	publish_name = serializers.CharField(max_length=32, source="publish.name", read_only=True)
	# Many to many fields
	authors_list = serializers.SerializerMethodField(read_only=True)
	def get_authors_list(self, book_obj):
		authors_queryset = book_obj.authors.all()
		return [{"id":author.id, "name":author.name} for author in authors_queryset]
	
	# Method called when adding data
	def create(self, validated_data):
		# {'title': 'Python666', 'price': Decimal('66.00'), 'publish': '2'}
        validated_data['publish_id'] = validated_data.pop('publish')
        book = Book.objects.create(**validated_data)
		
		return book
		
	# Method called when updating data
	def update(self, instance, validated_data):
        # Update data calls this method
        instance.title = validated_data.get('title', instance.title)
        instance.publishDate = validated_data.get('publishDate', instance.publishDate)
        instance.price = validated_data.get('price', instance.price)
        instance.publish_id = validated_data.get('publish', instance.publish.nid)

        instance.save()

        return instance
	
  • Define views.py
from rest_framework.response import Response
from rest_framework.views import APIView

class BookView(APIView):
	# Get all
	def get(self, request):
		books = Book.objects.all()
		serialized_data = BookSerializer(books, many=True)
		return Response(serialized_data.data)
	
	# New data
	def post(self, request):
		origin_data = request.data
		serialized_data = BookSerializer(data=origin_data)
		if serialized_data.is_valid():
			serialized_data.save()
			# Return new data
			return Response(serialized_data.data)
		else:
			# Return error message
			return Response(serialized_data.errors)
			

class BookFilterView(APIView):
	# Update data
	def put(self, request, pk):
		origin_data = request.data # Modified data
		obj = Book.objects.get(pk=pk)
		serialized_data = BookSerializer(data=origin_data, instance=obj)
		
		if serialized_data.is_valid():
			serialized_data.save()
			# Return modified data
			return Response(serialized_data.data)
		else:
			return Response(serialized_data.errors)
			
	# Delete data
	def delete(self, request, id):
        book_obj = Book.objects.get(pk=id).delete()

        return Response("")

	# Get single data
    def get(self, request, pk):
        book_obj = Book.objects.get(pk=pk)

        serialized_data = BookSerializer(book_obj, many=False)

        return Response(serialized_data.data)

First optimization: optimize interface logic with mixin

  • urls.py
from django.urls import re_path

urlpatterns = [
    re_path(r'books/$', views.BookView.as_view()),
    re_path(r'books/(?P<pk>\d+)/$', views.BookFilterView.as_view()),
]
  • views.py
# -*- coding: utf-8 -*-
from rest_framework.mixins import (
    ListModelMixin,
    CreateModelMixin,
    UpdateModelMixin,
    DestroyModelMixin,
    RetrieveModelMixin
)
from rest_framework.generics import GenericAPIView

# Modules in the current app
from .models import Book
from mixin_serializer import BookSerializer

# Create your views here.


class BookView(ListModelMixin, CreateModelMixin, GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

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

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class BookFilterView(DestroyModelMixin,
                     UpdateModelMixin,
                     RetrieveModelMixin,
                     GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

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

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)
  • DRF defines these five interfaces in different modelmixins. The steps are as follows:
  1. Import ModelMixin
  2. ModelMix required for view class inheritance
  3. Instead of inheriting APIView, you need to inherit generics.GenericAPIView
  4. There must be two class variables: queryset and serializer class
  5. There is no need to define any logical operation in the interface, and everything is handed to mixin
  6. The return values of each interface are different. The corresponding relationships are: {"get": "list", "delete": "destroy", "put": "update", "get": "retrieve", "post": "create"}

Second optimization: use view to optimize the interface logic

  • views.py
# -*- coding: utf-8 -*-
from rest_framework import generics

# Modules in the current app
from .models import Book
from .serializer_classes import BookSerializer

# Create your views here.


class BookView(generics.ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer


class BookFilterView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

The third Optimization: optimizing interface logic with viewset

  • urls.py
from django.urls import re_path

urlpatterns = [
    re_path(r'books/$', views.BookView.as_view({
        'get': 'list',
        'post': 'create'
    })),
    re_path(r'books/(?P<pk>\d+)/$', views.BookView.as_view({
        'get': 'retrieve',
        'put': 'update',
        'delete': 'destroy'
    })),
]
  • views.py
# -*- coding: utf-8 -*-
# django rest framework component
from rest_framework.viewsets import ModelViewSet

# Modules in the current app
from .models import Book
from .serializer_classes import BookSerializer

# Create your views here.


class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

Topics: Programming Django REST