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