Django rest_framework开发一组RESTFUL标准接口[ModelSerializer+GenericAPIView]

Django rest_framework开发一组RESTFUL标准接口[ModelSerializer+GenericAPIView]

不管何等复杂的业务逻辑,不管何等高效的开发框架,对后端来说最终都要落到对具体的某一个关系模型的增删改查上。
理论似乎没有,那就正式开始吧!


1 序列化为什么选ModelSerializer

1.1 序列化和反序列化

我们开发的HTTP接口,是用来传递数据的(入或出对应读和写)。从接口入的数据和从接口出来的数据,都是JSON格式的数据,这很棒,是我们想要的。但是我们知道,Django后端与数据库的交互方式,是通过ORM进行的,ORM不认(无法直接处理)JSON格式的数据,ORM需要object才能顺利和关系数据库交互。所以到这里我们应该已经有结论了,为什么要搞Serializer,其实很简单对吧,Serializer的作用就是:把从接口入的数据变成Django_ORM喜欢的object;把需要从接口出的数据从ORM给的object变为前端喜欢的JSON!就是这么棒,这是一个很牛掰、较易理解的处理方式对吧。那么这两种处理方式,总得有个名儿吧,So,前者叫反序列化(JSON-object);后者叫序列化(object-JSON)!

1.2 ModelSerializer 用起来就是这么爽

Serializer我们要指定前端接收哪些字段值,不仅要一个一个指定字段,还要一个一个设置对该字段的约束,麻烦!我们搞开发的,估计是最讨厌磨磨唧唧的一群人。
好,于是ModelSerializer横空出世!它让我们只需简单的配置哪个模型、哪些字段、什么约束即可。于是乎ModelSerializer变成了这个样子:


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}
        }

多么的优雅!


围绕Client模型的一组RESTFUL标准接口,先从模型开始。


2 定义Client模型

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']

定义模型和之前并无区别,不过如果有若干个相互关联的模型,还是要保证关系模型的设计要至少达到第三范式,减小关系模型的耦合度。不然,后期等业务发生变化的时候,低范式的关系模型,会让你发狂。


3 定义Client模型的ModelSerializer

为了保证ModelSerializer的优雅,我们为创建、查询、分页过滤创建不同的序列化器:

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__'

使用rest_framework进行接口开发的过程中,Serializer承担了原来views的功能,即实现业务逻辑,你也可以在views中重写create或update方法,但是重写Serializer的create和update更易理解。


4 views视图 犹抱琵琶半遮面

序列化器承担了复杂的业务逻辑编写,视图Views想不优雅都很难。Views中主要是做配置,配置序列化器、分页器、过滤器、身份认证方式、权限认证方式等等。
对模型Client,我们创建3个视图,分别对应上面的三个序列化器,这么干也符合RESTFUL接口标准。

4.1 自定义分页器

在APP下创建page.py,添加以下代码:

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 自定义过滤器

在APP下创建filters.py,添加以下代码:

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 定义视图

在APP下views.py中添加以下代码:

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 配置路由

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()),
]

以上。

猜你喜欢

转载自blog.csdn.net/qq_42774234/article/details/131429795