使用restframework框架开发接口,方式应该有6、7种,每个人的习惯不同,用的方法也不一样,再次不再一一详述。
我比较常用:ModelSerializer+GenericAPIView
原因是用视图函数+装饰器、视图类+继承APIView、或者混入Mixin这三种封装层次有点低,用一个封装层次低的接口,通常意味着你需要写更多的代码,后期也需投入更多的精力去维护它,当然,好处是写出来的代码比较容易看懂;而使用ViewSets(视图集)则刚好相反,ViewSets封装了GenericAPIView,它显得有些画蛇添足,过高的封装层次可能会让你感到云里雾里,当然,好处是用熟了之后会很爽。
所以,在能理解和接受的程度与接口封装的层次两方面来权衡,我选择了GenericAPIView来写视图,ModelSerializer当然也比单纯的Serializer更好用,写更少的代码,做更多的事。
Django框架它整个采用的是MVT的架构,这三部分各司其职,由M负责与数据库的实际交互;V负责业务逻辑;T负责接受请求与展示响应(实际就是前端)。那我们可以这么理解,只要有一个东西它具备了接受请求(入参)与展示响应(返回值)的功能,我们就可以把它当成T,因为它具备了T的功能。前后端不分离的时候,一切都是那么的美好。
当前后端分离的时候,我们突然发现,T不见了。那么谁来充当T的角色呢,没错是Serializer(负责接受请求与展示响应)。这样一来,前后端分离与不分离,就有了一个统一的架构,也即一个接口通常由三大主要的部分组成:模型、视图、序列化器。
在Django框架的MVT架构中,M承担了与数据库进行交互的功能,但是由于我们用的是ORM,所以只需要将python对象映射到数据模型即可,也就是定义python对象,并在该对象中声明相应的字段。需要注意的一点是,在定义python对象之前,需要先绘制ER图,明确实体间的关系,确保每一个实体,都至少遵循第三范式(3NF)。
说明:前后端分离与不分离,models并没有什么区别
前后端不分离的时候,T其实就是前端,接受请求并返回响应数据。
前后端分离的时候,序列化器承担了这个功能,接受前端请求返回响应数据。
如果使用ModelSerializer来定义序列化器,那么它大概长这个样子:
"""
序列化器
"""
from rest_framework import serializers
from .models import *
import re
class MyModelSerializer(serializers.ModelSerializer):
"""
MyModel 序列化器
"""
class Meta:
"""
model 模型
fields 接口入参
extra_kwargs 入参的约束
"""
model = MyModel
fields = ('name', 'mobile')
extra_kwargs = {
'mobile': {
'write_only': True,
'min_length': 8,
'max_length': 16,
}
}
def validate_name(self, name):
"""
对name的校验
"""
if User.objects.filter(username=username).count():
raise serializers.ValidationError("该用户名已被注册")
return name
def validate_mobile(self, mobile):
"""
判断手机号格式
判断手机号是否已注册
"""
# 注册
if User.objects.filter(mobile=mobile).count():
raise serializers.ValidationError("该手机号已被注册")
# 判断手机号码格式是否有误
REGEX_MOBILE = '1[358]\d{9}$|^147\d{8}$|^176\d{8}$'
# 格式
if not re.match(REGEX_MOBILE, mobile):
raise serializers.ValidationError("手机号格式有误")
return mobile
def create(self, validated_data):
"""
validated_data 通过校验的数据 是一个字典
Serializer中重写create可以对数据做一些修改
最终将返回一个实例 该实例会给到对应的视图View
"""
user = super().create(validated_data)
# Your code
return user
在序列化器Serializer中,容易让人感到困惑的可能就是前端字段校验这一块。其实,我们回到Serializers的功能接受前端请求返回响应数据,就能明白为什么它要序列化与反序列化。
在反序列化的过程中,我们不希望用户输入一些非法的参数,所以要在Serializer中定义入参的约束与自定义的校验方式,校验通过则返回一个模型的实例给视图,否则返回错误信息。
这就是Serializer的功能与Model及View之间的关系。
模型和序列化器固然重要,但是视图才是核心,因为通常情况下,业务逻辑都集中在views中,由视图完成。
在视图中你可以通过重写get/create方法,完成业务逻辑。
如果你像我一样使用的是GenericAPIView来写视图函数,那么你的View应该长这个样子:
class MyModelCreateView(generics.CreateAPIView):
"""
创建视图
"""
# permission_classes = [permissions.IsAuthenticated]
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
def post(self, request, *args, **kwargs):
"""
重写post 四核可以不用重写
"""
serializer_data = MyModelSerializer(data=request.data)
if serializer_data.is_valid():
return super().post(request, *args, **kwargs)
else:
return Response(serializer_data.errors)
def create(self, request, *args, **kwargs):
"""
重写create 写自己的业务逻辑
如果继承的是ListAPIView 就重写create
"""
# 获取前端传入的数据
field= request.POST.get("xx")
# Your code
return JsonResponse(
data={
'data': data,
'msg': 'OK',
'code': 1,
},
safe=False
)
重写create/get方法时,通过reques获取从前端传过来的入参,拿到入参之后,你就可以写自己的业务逻辑了。
我通常是先写模型,然后是序列化器,最后再写业务逻辑以及接口的其他功能,每个人的方法可能不同,也就不详述了。