• 【Django】 rest_framework接口开发流程及接口功能组成


    restframework 接口开发流程及接口功能组成


    使用restframework框架开发接口,方式应该有6、7种,每个人的习惯不同,用的方法也不一样,再次不再一一详述。
    我比较常用:ModelSerializer+GenericAPIView
    原因是用视图函数+装饰器、视图类+继承APIView、或者混入Mixin这三种封装层次有点低,用一个封装层次低的接口,通常意味着你需要写更多的代码,后期也需投入更多的精力去维护它,当然,好处是写出来的代码比较容易看懂;而使用ViewSets(视图集)则刚好相反,ViewSets封装了GenericAPIView,它显得有些画蛇添足,过高的封装层次可能会让你感到云里雾里,当然,好处是用熟了之后会很爽。
    所以,在能理解和接受的程度与接口封装的层次两方面来权衡,我选择了GenericAPIView来写视图,ModelSerializer当然也比单纯的Serializer更好用,写更少的代码,做更多的事。


    在这里插入图片描述



    1 Django rest_framework开发的一个符合RESTful标准的接口组成及功能

    Django框架它整个采用的是MVT的架构,这三部分各司其职,由M负责与数据库的实际交互;V负责业务逻辑;T负责接受请求与展示响应(实际就是前端)。那我们可以这么理解,只要有一个东西它具备了接受请求(入参)与展示响应(返回值)的功能,我们就可以把它当成T,因为它具备了T的功能。前后端不分离的时候,一切都是那么的美好。
    当前后端分离的时候,我们突然发现,T不见了。那么谁来充当T的角色呢,没错是Serializer(负责接受请求与展示响应)。这样一来,前后端分离与不分离,就有了一个统一的架构,也即一个接口通常由三大主要的部分组成:模型、视图、序列化器

    1.1 模型M(models.py)

    在Django框架的MVT架构中,M承担了与数据库进行交互的功能,但是由于我们用的是ORM,所以只需要将python对象映射到数据模型即可,也就是定义python对象,并在该对象中声明相应的字段。需要注意的一点是,在定义python对象之前,需要先绘制ER图,明确实体间的关系,确保每一个实体,都至少遵循第三范式(3NF)。

    说明:前后端分离与不分离,models并没有什么区别
    
    • 1

    1.2 序列化器T(Serializers.py)

    前后端不分离的时候,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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    在序列化器Serializer中,容易让人感到困惑的可能就是前端字段校验这一块。其实,我们回到Serializers的功能接受前端请求返回响应数据,就能明白为什么它要序列化与反序列化。

    • 序列化:python对象转变为可传输(可被用于前端渲染)的JSON格式(也可能是xml等)字符串,究其原因是因为我们用的ORM,第一步ORM读数据,拿出来的是一个查询集(set对象),需要把它变成前端喜欢的样子。
    • 反序列化字符串变为python对象。从前端得到的入参,必然是字符串格式,想要把它存到数据库里,还得靠ORM,但是ORM喜欢的是python对象,所以需要一个反序列化的过程。

    在反序列化的过程中,我们不希望用户输入一些非法的参数,所以要在Serializer中定义入参的约束与自定义的校验方式,校验通过则返回一个模型的实例给视图,否则返回错误信息。
    这就是Serializer的功能与Model及View之间的关系。

    1.3 视图V(views.py)

    模型和序列化器固然重要,但是视图才是核心,因为通常情况下,业务逻辑都集中在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
            )
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    重写create/get方法时,通过reques获取从前端传过来的入参,拿到入参之后,你就可以写自己的业务逻辑了。


    2 Django DRF 接口开发步骤

    • 模型设计,需要注意关系规范化
    • 序列化器,需要知道哪些是入参,分别需要怎样的约束
    • 视图,写业务逻辑、权限配置、过滤查询分页等

    我通常是先写模型,然后是序列化器,最后再写业务逻辑以及接口的其他功能,每个人的方法可能不同,也就不详述了。

  • 相关阅读:
    怎么把两首歌曲拼接在一起?
    达梦数据库修改最大连接数
    Vue——props配置
    Haskell 的 IO
    详解UDS CAN诊断:DiagnosticSessionControl Service(SID:0X10)
    SSM项目源码基于SSM实现的小说网站含前后台
    力扣203 - 移除链表元素【LeetCode转VS调试技巧教学】
    为什么说 HashMap 是无序的
    CentOS6.6下安装git 2.6.2
    python LeetCode 刷题记录 83
  • 原文地址:https://blog.csdn.net/qq_42774234/article/details/133090421