不管何等复杂的业务逻辑,不管何等高效的开发框架,对后端来说最终都要落到对具体的某一个关系模型的增删改查上。
理论似乎没有,那就正式开始吧!
我们开发的HTTP接口,是用来传递数据的(入或出对应读和写)。从接口入的数据和从接口出来的数据,都是JSON格式的数据,这很棒,是我们想要的。但是我们知道,Django后端与数据库的交互方式,是通过ORM进行的,ORM不认(无法直接处理)JSON格式的数据,ORM需要object才能顺利和关系数据库交互。所以到这里我们应该已经有结论了,为什么要搞Serializer,其实很简单对吧,Serializer的作用就是:把从接口入的数据变成Django_ORM喜欢的object;把需要从接口出的数据从ORM给的object变为前端喜欢的JSON!就是这么棒,这是一个很牛掰、较易理解的处理方式对吧。那么这两种处理方式,总得有个名儿吧,So,前者叫反序列化(JSON-object);后者叫序列化(object-JSON)!
Serializer我们要指定前端接收哪些字段值,不仅要一个一个指定字段,还要一个一个设置对该字段的约束,麻烦!我们搞开发的,估计是最讨厌磨磨唧唧的一群人。
好,于是ModelSerializer横空出世!它让我们只需简单的配置哪个模型、哪些字段、什么约束即可。于是乎ModelSerializer变成了这个样子:
class ExampleModelSerializer(serializers.ModelSerializer):"""example 序列化器"""class Meta:"""在这儿配置就OK"""# 模型 前端需要的字段 字段约束model = ClientDispatchBlackListfields = ('name', 'mobile', 'demo')extra_kwargs = {'name': {'required': True},'mobile': {'required': True},'demo': {'required': True}}
多么的优雅!
围绕Client模型的一组RESTFUL标准接口,先从模型开始。
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']
定义模型和之前并无区别,不过如果有若干个相互关联的模型,还是要保证关系模型的设计要至少达到第三范式,减小关系模型的耦合度。不然,后期等业务发生变化的时候,低范式的关系模型,会让你发狂。
为了保证ModelSerializer的优雅,我们为创建、查询、分页过滤创建不同的序列化器:
from rest_framework import serializers
dels import User
from .models import *
import reclass ClientCreateModelSerializer(serializers.ModelSerializer):"""Client 客户 创建 序列化器"""class Meta:model = Clientfields = ('name', 'mobile')# extra_kwargs 可对字段做约束def validate_mobile(self, mobile):"""格式validate_要校验的字段名判断手机号格式"""REGEX_MOBILE = '1[358]d{9}$|^147d{8}$|^176d{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):# passclass ClientUpdateModelSerializer(serializers.ModelSerializer):"""Client 客户 编辑/修改/删除 序列化器"""class Meta:model = Clientfields = '__all__'# 电话只读 不允许修改extra_kwargs = {'mobile': {'read_only': True}}# 如果业务逻辑很复杂 就重写update# def update(self, instance, validated_data):# passclass ClientReadModelSerializer(serializers.ModelSerializer):"""Client 客户 读取 序列化器"""class Meta:model = Clientfields = '__all__'
使用rest_framework进行接口开发的过程中,Serializer承担了原来views的功能,即实现业务逻辑,你也可以在views中重写create或update方法,但是重写Serializer的create和update更易理解。
序列化器承担了复杂的业务逻辑编写,视图Views想不优雅都很难。Views中主要是做配置,配置序列化器、分页器、过滤器、身份认证方式、权限认证方式等等。
对模型Client,我们创建3个视图,分别对应上面的三个序列化器,这么干也符合RESTFUL接口标准。
在APP下创建page.py,添加以下代码:
from rest_framework.pagination import PageNumberPaginationclass CustomPagination(PageNumberPagination):"""自定义分页器 通用"""page_size = 10max_page_size = 50page_size_query_param = 'size'page_query_param = 'page'
在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 = Clientfields = ('name', 'mobile')
在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 = ClientCreateModelSerializerclass ClientDetailView(generics.RetrieveUpdateDestroyAPIView):"""客户 编辑/修改/删除"""# permission_classes = [permissions.IsAuthenticated]queryset = Client.objects.all()serializer_class = ClientUpdateModelSerializerclass ClientReadView(generics.ListAPIView):"""客户 读取 分页 过滤 搜索"""# permission_classes = [permissions.IsAuthenticated]queryset = Client.objects.all()serializer_class = ClientReadModelSerializer# 自定义分页器 还可配置过滤器 搜索等pagination_class = CustomPaginationfilter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)filterset_class = ClientFilterordering_fields = ('create_time',)# 如果搜索字段是外键 用字段名__关联模型字段名search_fields = ('name', 'mobile')
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()),
]
以上。
本文发布于:2024-02-02 06:54:39,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170682808042114.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |