Django rest_framework develops a set of RESTFUL standard interfaces [ModelSerializer+GenericAPIView]

Django rest_framework develops a set of RESTFUL standard interfaces [ModelSerializer+GenericAPIView]

No matter how complex the business logic is, no matter how efficient the development framework is, for the backend, it will eventually fall on adding, deleting, modifying and checking a specific relational model.
There seems to be no theory, so let's get started!


1 Why choose ModelSerializer for serialization

1.1 Serialization and deserialization

The HTTP interface we developed is used to transfer data (in or out corresponds to reading and writing). The data input from the interface and the data output from the interface are all in JSON format, which is great and what we want. But we know that the Django backend interacts with the database through ORM. ORM does not recognize (cannot directly process) data in JSON format. ORM needs objects to interact with relational databases smoothly. So here we should have come to a conclusion, why use Serializer, in fact, it is very simple, the role of Serializer is: to change the data input from the interface into the object that Django_ORM likes; to change the data that needs to be output from the interface from the object given by ORM to the JSON that the front end likes! It’s that great, it’s an awesome, easy-to-understand way of doing things, right? So these two processing methods must have a name, So, the former is called deserialization (JSON-object); the latter is called serialization (object-JSON)!

1.2 ModelSerializer is so cool to use

Serializer We need to specify which field values ​​​​are received by the front end, not only to specify the fields one by one, but also to set constraints on the fields one by one, trouble! We are engaged in development, probably the group of people who hate moaning the most.
Ok, so ModelSerializer was born! It allows us to simply configure which model, which fields, and what constraints. So ModelSerializer became like this:


class ExampleModelSerializer(serializers.ModelSerializer):
    """
    example 序列化器
    """

    class Meta:
		"""
		在这儿配置就OK
		"""
		# 模型 前端需要的字段 字段约束
        model = ClientDispatchBlackList
        fields = ('name', 'mobile', 'demo')

        extra_kwargs = {
    
    
            'name': {
    
    'required': True},
            'mobile': {
    
    'required': True},
            'demo': {
    
    'required': True}
        }

What elegance!


A set of RESTFUL standard interfaces around the Client model, starting with the model.


2 Define the Client model

class Client(models.Model):
    """
    客户
    """
    
    name = models.CharField(max_length=32, verbose_name="姓名")
    mobile = models.CharField(max_length=11, primary_key=True, verbose_name="移动电话")
    create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
    	"""
		默认排序字段
		"""
        ordering = ['create_time']

The definition model is the same as before, but if there are several interrelated models, it is still necessary to ensure that the design of the relational model reaches at least the third normal form to reduce the coupling degree of the relational model. Otherwise, when the business changes later, the low-paradigm relationship model will drive you crazy.


3 Define the ModelSerializer of the Client model

In order to ensure the elegance of ModelSerializer, we create different serializers for creation, query, and pagination filtering:

from rest_framework import serializers
from user.models import User
from .models import *
import re


class ClientCreateModelSerializer(serializers.ModelSerializer):
    """
    Client 客户 创建 序列化器
    """

    class Meta:
        model = Client
        fields = ('name', 'mobile')
    	
    	# extra_kwargs 可对字段做约束

    def validate_mobile(self, mobile):
        """
        格式validate_要校验的字段名
        判断手机号格式
        """

        REGEX_MOBILE = '1[358]\d{9}$|^147\d{8}$|^176\d{8}$'

        # 格式
        if not re.match(REGEX_MOBILE, mobile):
            raise serializers.ValidationError("手机号格式有误")

        # 是否已有档案
        if Client.objects.filter(mobile=mobile).count():
            raise serializers.ValidationError("该客户已存在")
        
        return mobile
	
	# 如果你的业务逻辑很复杂重写create
    # def create(self, validated_data):
    #	pass
       

class ClientUpdateModelSerializer(serializers.ModelSerializer):

    """
    Client 客户 编辑/修改/删除 序列化器
    """

    class Meta:
        model = Client
        fields = '__all__'
		
		# 电话只读 不允许修改
        extra_kwargs = {
    
    
            'mobile': {
    
    'read_only': True}
        }
    
    # 如果业务逻辑很复杂 就重写update
    # def update(self, instance, validated_data):
    #	pass
       


class ClientReadModelSerializer(serializers.ModelSerializer):
    """
    Client 客户 读取 序列化器
    """

    class Meta:
        model = Client
        fields = '__all__'

In the process of using rest_framework for interface development, Serializer assumes the function of the original views, that is, to implement business logic. You can also rewrite the create or update method in views, but rewriting the create and update of Serializer is easier to understand.


4 views The view still holds the pipa half-hidden

The serializer undertakes complex business logic writing, and it is difficult for Views to be elegant. Views is mainly for configuration, configuring serializers, pagers, filters, identity authentication methods, permission authentication methods, and so on.
For the model Client, we create three views, corresponding to the above three serializers, which also conform to the RESTFUL interface standard.

4.1 Custom pager

Create page.py under APP and add the following code:

from rest_framework.pagination import PageNumberPagination

class CustomPagination(PageNumberPagination):
    """
    自定义分页器 通用
    """

    page_size = 10
    max_page_size = 50
    page_size_query_param = 'size'
    page_query_param = 'page'

4.2 Custom Filters

Create filters.py under APP and add the following code:

from django_filters import rest_framework as filter
from .models import *


class ClientFilter(filter.FilterSet):
    """
    咨询信息 过滤器
    """

    name = filter.CharFilter(field_name='source', lookup_expr='icontains')
    mobile = filter.CharFilter(field_name='status', lookup_expr='exact')


    class Meta:
        model = Client
        fields = ('name', 'mobile')

4.3 Defining Views

Add the following code in views.py under APP:

from django.shortcuts import render
from rest_framework import generics
from rest_framework import permissions
from .seriailzers import *
from .page import *
from .models import *
from .filters import *


class ClientView(generics.CreateAPIView):
    """
    客户 创建
    """
    
    # 如果要做权限认证 那么先配置身份认证 authentication_classes
    # permission_classes = [permissions.IsAuthenticated]
    queryset = Client.objects.all()
    serializer_class = ClientCreateModelSerializer


class ClientDetailView(generics.RetrieveUpdateDestroyAPIView):
    """
    客户 编辑/修改/删除
    """

    # permission_classes = [permissions.IsAuthenticated]
    queryset = Client.objects.all()
    serializer_class = ClientUpdateModelSerializer


class ClientReadView(generics.ListAPIView):
    """
    客户 读取 分页 过滤 搜索
    """
    
    # permission_classes = [permissions.IsAuthenticated]
    queryset = Client.objects.all()
    serializer_class = ClientReadModelSerializer
	
	# 自定义分页器 还可配置过滤器 搜索等
    pagination_class = CustomPagination

	filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    filterset_class = ClientFilter
    
    ordering_fields = ('create_time',)
    
    # 如果搜索字段是外键 用字段名__关联模型字段名
    search_fields = ('name', 'mobile')

5 Configure routing

from django.urls import path
from .views import *

# 需要在全局配置文件settings.py中 include当前APP的urls.py
urlpatterns = [
    path('client/', ClientView.as_view()),
    path('client/<pk>/', ClientDetailView.as_view()),
    path('clients/', ClientReadView.as_view()),
]

that's all.

Guess you like

Origin blog.csdn.net/qq_42774234/article/details/131429795