• 十大接口


    十大接口

    一、Response响应封装

    1.1封装

    from rest_framework.response import Response
    class APIResponse(Response):
        def __init__(self, status=0, msg="ok", results=None, http_status=None, headers=None, exception=False, **kwargs):
            data_dic = {  # json的response基础有数据状态码和数据状态信息
                "status": status,
                "msg": msg,
            }
    
            if results is not None:  # 后台有数据,响应数据
                data_dic['results'] = results
            if kwargs:
                data_dic.update(**kwargs)  # 后台的一切自定义响应数据直接放到响应数据data中
    
            super().__init__(data=data_dic, status=http_status, headers=headers, exception=exception)
    
            
           
    

    1.2使用

    class MyAPIView(APIView):
        def get(self, request, *args, **kwargs):
    
            pk = kwargs.get("pk")
            if pk:
                book_obj = models.Book.objects.filter(pk=pk).first()
                if not book_obj:               
                    return APIResponse(status=1, msg='get error')
                
                book_ser = BookSerializers(book_obj).data
                print(book_ser)           
                return APIResponse(results=book_ser)
            else:
    
                book_obj = models.Book.objects.all()
                book_list_obj = BookSerializers(book_obj, many=True).data
                print(book_list_obj)
                return APIResponse(results=book_list_obj)
    

    二、书连表查询

    2.1连表查询

    # models.py
    class Book(BaseModel):  # 书
        name = models.CharField(max_length=49)
        price = models.DecimalField(max_digits=5, decimal_places=2)
    
        # 出版社与书是一对多的关系,                设置反向查询字段     断外键之间的关系      设置级联,不进行级联删除(出版社删了,书不删) 一对多关系
        publish = models.ForeignKey(to="Publish", related_name="books", db_constraint=False, on_delete=models.DO_NOTHING)
    
        # 书与作者是多对多的关系                      断关联
    
        # 在多对多外键实际在关系表中,ORM默认关系表中两个外键都是级联
        # ManyToManyField字段不提供设置on_delete,如果想设置关系表级联,只能手动定义创建第三张关系表
        author = models.ManyToManyField(to="Author", related_name="books", db_constraint=False)
    
        # 自定义连表深度,不需要反序列化,因为自定义插拔属性不参与反序列化
        @property
        def publish_name(self):
            return self.publish.name
    	# 连表查询
        @property
        def author_list(self):
            temp_author_list = []
            for author in self.author.all():
                temp_author_list.append({
                    'name': author.name,
                    'sex': author.get_sex_display(),
                    'mobile': author.detail.mobile
                })
            return temp_author_list
    # serializers.py 序列化类
    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = ("name", "price", "publish_name" ,"author_list")
    # views.py
    class MyAPIView(APIView):
        # 单查和群查
    
        def get(self, request, *args, **kwargs):
    
            pk = kwargs.get("pk")
            if pk:
    			# 单挑数据
                book_obj = models.Book.objects.filter(pk=pk, is_delete=False).first()
    
                if not book_obj:
                    return APIResponse(status=1, msg='get error')
    			
                book_ser = BookSerializers(book_obj, is_delete=False).data
                print(book_ser)
    
                return APIResponse(results=book_ser)
            else:
    
                book_obj = models.Book.objects.all()
    			# 全部数据
                book_list_obj = BookSerializers(book_obj, many=True).data
                print(book_list_obj)
                return APIResponse(results=book_list_obj)
    
    

    总结

    1. 连表查询在modes.py中自定义的字段,一旦其中的逻辑出错,他对应的返回值就不会做出任何响应
    2. 自定义连表深度,不需要反序列化,因为自定义插拔属性不参与反序列化
    3. 子序列化可以辅助快速实现自定义外键深度的序列化,但是不能进行反序化,__all__

    2.2指定字段**

    1) 使用fields来明确字段, __all__ 表名包含所有字段,也可以写明具体哪些字段,如
    class BookInfoSerializer(serializers.ModelSerializer):
     """图书数据序列化器"""
     class Meta:
     model = BookInfo
     fields = "__all__"
    
    2) 使用exclude可以明确排除掉哪些字段
    class BookInfoSerializer(serializers.ModelSerializer):
     """图书数据序列化器"""
     class Meta:
     model = BookInfo
     exclude = ('id',)
    
    3) 指明只读字段
    可以通过read_only_fields指明只读字段,即仅用于序列化输出的字段
    class BookInfoSerializer(serializers.ModelSerializer):
     """图书数据序列化器"""
     class Meta:
     model = BookInfo
     fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
     read_only_fields = ('id', 'bread', 'bcomment')
    
    3、添加额外参数
    我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
    class BookInfoSerializer(serializers.ModelSerializer):
     """图书数据序列化器"""
     class Meta:
     model = BookInfo
     fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
     extra_kwargs = {
     'bread': {'min_value': 0, 'required': True},
     'bcomment': {'min_value': 0, 'required': True},
     }
    

    三、单查和群查接口

    urlpatterns = [
        # url(r'^admin/', admin.site.urls),
        url(r'^books/$', views.BookAPIView.as_view()),
    
        url(r'^books/(?P<pk>d+)/', views.BookAPIView.as_view()),
    
    ]
    
    
    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            # 1.多表连查
            fields = ("name", "price", "publish_name" ,"author_list")
            # 2.__all__ 获取所有字段
            # fields = "__all__"
    
            # 3. __exclude__ 除了这个字段
            # exclude = ('id', )
            # 4. depth 深度查询, 与__all__一起连用
            # depth = 2
    
    class BookAPIView(APIView):
        """
            单查:前台数据为pk,接口为 /books/(pk)/
            群查:前台数据为pks,接口为 /books/
        """
        # 单查和群查
        def get(self, request, *args, **kwargs):
    
            pk = kwargs.get("pk")
            if pk:
                # 单查
                book_obj = models.Book.objects.filter(pk=pk, is_delete=False).first()
                # 判断
                if not book_obj:
                    return APIResponse(status=1, msg='get error', http_status=400)
                # 返回数据
                book_data = BookSerializers(book_obj, is_delete=False).data
                return APIResponse(results=book_data)
            else:
                
                # 群查
                book_obj = models.Book.objects.all()
                book_list_data = BookSerializers(book_obj, many=True).data
                return APIResponse(0, "ok", results=book_list_data)
    

    总结:

    1. 单查从请求中获取get单条数据
    2. 过滤False数据库中的记录
    3. 群查序列化,many设置True
    4. 单查群查接口,序列化类提供序列化对象,many参数控制着操作的数据是一条还是多条

    四、单删和群删接口

    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            # 1.多表连查
            fields = ("name", "price", "publish_name" ,"author_list")
    
     def delete(self, request, *args, **kwargs):
            """"
            单删:前台数据为pk,接口为 /books/(pk)/
            群删:前台数据为pks(json),接口为 /books/
            """
            pk = kwargs.get("pk")
             # 将单删群删逻辑整合
            if pk:  # /books/(pk)/的接口就不考虑群删,就固定为单删 请求要带斜杠
                pks = [pk]  # 获取单删
            else:
                # 获取群删
                pks = request.data.get("pk")
    
            # 判断前台是否是否pk
            if not pks:
                # 前台数据有误,没有提供pk
                return APIResponse(1, "delete error", http_status=400)
    
            # 返回操作的行,受影响行,就是删除成功,反之失败
            rows = models.Book.objects.filter(is_delete=False, pk__in=pks).update(is_delete=True)
            # 判断是否删除成功
            if rows:
                return APIResponse(0, "delete ok")
            else:
                return APIResponse(0, "delete error")
    

    总结:

    1. delete请求的时候url要添加斜杠,2的后面

    2. 将单删和群删进行逻辑整合

    3. 单删群删接口,后台操作删除字段即可,前台7提供pk就是单删,提供pks就是群删

    五、单增和群增接口

    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            # 1.多表连查
            fields = ("name", "price", "publish_name", "author_list", 'publish', 'author')
            extra_kwargs = {
                "publish": {
                    "write_only": True  # 制作反序列化,不做序列化
                },
                "author": {
                    "write_only": True
                }
            }
    
    
    class BookAPIView(APIView): 
        def post(self, request, *args, **kwargs):
    		"""
    		 """
             save源码
               if self.instance is not None:
                self.instance = self.update(self.instance, validated_data)
                assert self.instance is not None, (
                    '`update()` did not return an object instance.'
                )
            else:
                self.instance = self.create(validated_data)
                assert self.instance is not None, (
                    '`create()` did not return an object instance.'
                )
    		"""
            request_data = request.data
            print(request_data)
    
            # 单填
            if isinstance(request_data, dict):
                # 校验单条数据
                book_result = BookSerializers(data=request_data)
                # 获取校验结果
                if book_result.is_valid(raise_exception=True):
                    book_obj = book_result.save()
                    # 返回序列化对象
                    return APIResponse(0, "post ok", results=BookSerializers(book_obj).data)
            # 群填
            elif isinstance(request_data, list) and request_data:
    
                # 校验多条数据
                book_result = BookSerializers(data=request_data, many=True)
                if book_result.is_valid(raise_exception=True):
                    # 返回保存对象列表
                    book_list_obj = book_result.save()
                    # 返回序列化结果
                    result = BookSerializers(book_list_obj, many=True)
                    return APIResponse(0, 'data ok ', results=result)
    
            else:
                # 其他错误
                return APIResponse(1, "data error", http_status=400)
    
    

    总结:

    1. 单条数据为字典,判断是否为字典 ,对数据进行校验,校验结果由is_valid进行处理,保存对象,返回序列化对象
    2. 多条数据,判断是否为列表,列表是否为空,对象进行校验,设置mandy为True校验多条数据,校验结果又is_valid进行处理,保存对象,返回序列化对象结果多条mandy为True
    3. 单增群增接口,根据数据判断是单增还是群增,对应序列化类要设置many,而序列化类只需要通过data即可

    六、单条数据整改和多条数据整改

    # 序列化.py
    class BookListSerializers(serializers.ListSerializer):
        """
        # 1. create方法父级ListSerializer已经提供了
          def create(self, validated_data):
          通过self.child来访问绑定的ModelSerializer
            return [
                self.child.create(attrs) for attrs in validated_data
            ]
        """
    
        # 2、父级ListSerializer没有通过update方法的实现体,需要自己重写
        def update(self, instance, validated_data):
            # ModelSerializer中的update方法
            return [
                # 单个对象     当前要修改的数据
                self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
            ]
    
    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            list_serializer_class = BookListSerializers
            model = models.Book
            # 1.多表连查
            fields = ("name", "price", "publish_name", "author_list", 'publish', 'author')
            extra_kwargs = {
                "publish": {
                    "write_only": True  # 制作反序列化,不做序列化
                },
    
                "author": {
                    "write_only": True
                }
    
            }
    
    class BookAPIView(APIView):
        # 单整体改,群整体改
        def put(self, request, *args, **kwargs):
            """
             save源码
               if self.instance is not None:
                self.instance = self.update(self.instance, validated_data)
                assert self.instance is not None, (
                    '`update()` did not return an object instance.'
                )
            else:
                self.instance = self.create(validated_data)
                assert self.instance is not None, (
                    '`create()` did not return an object instance.'
                )
            单整体改: 前台提交字典,根据pk一个数据,接口/books/(pk)/
            群整体改: 前台提交列表套字典, 接口 /books/ 注每一个字典都可以通过pk添加
            """
            # 单改,将获取的json数据,通过获取pk对应数据库对象记录,进行修改数据
            pk = kwargs.get("pk")
            request_data = request.data
    
            print(request_data)
    
            if pk:
                try:
                    book_obj = models.Book.objects.get(pk=pk)
                except:
                    return APIResponse(1, "pk error")
    
                # 修改和新增,都需要通过数据,数据依旧给data,修改和新增不同点,需要将被修改对象给instance
                book_ser = BookSerializers(initial=book_obj, data=request_data)
                book_ser.is_valid(raise_exception=True)
                # 在保存数据之前必须调用 is_valid,在保存数据之前不可以调用book_ser不可以调用data属性,以为会提前产生_data
    
                book_new_obj = book_ser.save()
                return APIResponse(results=BookSerializers(book_new_obj).data)
            else:  # 群改
                if not isinstance(request_data, list) or len(request_data) == 0:
                    return APIResponse(1, "data error", http_status=400)
    
                # [{pk:1,...}, {pk:3,...}, {pk:100,...}] => [obj1, obj3, obj100] + [{...}, {...}, {...}]
                # 要考虑pk对应的对象是否被删,以及pk没有对应的对象
                # 假设pk3被删,pk100没有 => [obj1] + [{...}]
    
                # 注: 一定不要在循坏体重对循坏对象进行增删(影响对象的长度的操作
    
                obj_list = []
                data_list = []
    
                for dic in request_data:
                    try:
                        pk = dic.pop("pk")
                        try:
                            obj = models.Book.objects.get(pk=pk, is_delete=False)
                            # 获取对象是否存在
                            obj_list.append(obj)
                            # 添加数据
                            data_list.append(dic)
                        except:
                            pass
                    except:
                        return APIResponse(1, "data error", http_status=400)
                #                          修改的对象列表     对应的修改的数据 多条
                book_ser = BookSerializers(instance=obj_list,data=data_list, many=True)
                # 校验数据
                book_ser.is_valid(raise_exception=True)
                book_list_obj = book_ser.save()
                # 返回序列化修改的数据
                return APIResponse(results=BookSerializers(book_list_obj, many=True).data)
    

    总结:

    1. 单整体改和群整体改每个字段必须填,
    2. 没有提供整体改的方法需要自定义类继承ListSerializer类重写update方法,需要在子类进行绑定list_serializer_class = BookListSerializers
    3. 单整体改传参BookSerializers(initial=book_obj, data=request_data)
    4. 群整体改BookSerializers(instance=obj_list,data=data_list, many=True)
    5. 群改,前台提供的数据,后台要转化成要修改的对象们和用来更新的数据们,ModelSerializer设置list_serializer_class关联自己的ListSerializer,重写update方法,完成群改

    七、单局部改和群局部改

    # 序列化.py
    class BookListSerializers(serializers.ListSerializer):
        """
        # 1. create方法父级ListSerializer已经提供了
          def create(self, validated_data):
          通过self.child来访问绑定的ModelSerializer
            return [
                self.child.create(attrs) for attrs in validated_data
            ]
        """
    
        # 2、父级ListSerializer没有通过update方法的实现体,需要自己重写
        def update(self, instance, validated_data):
            # ModelSerializer中的update方法
            return [
                # 单个对象     当前要修改的数据
                self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
            ]
    
    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            list_serializer_class = BookListSerializers
            model = models.Book
            # 1.多表连查
            fields = ("name", "price", "publish_name", "author_list", 'publish', 'author')
            extra_kwargs = {
                "publish": {
                    "write_only": True  # 制作反序列化,不做序列化
                },
    
                "author": {
                    "write_only": True
                }
    
            }
    
    class BookAPIView(APIView):
     # 单局部改、群局部改
        def patch(self, request, *args, **kwargs):
            """
             save源码
               if self.instance is not None:
                self.instance = self.update(self.instance, validated_data)
                assert self.instance is not None, (
                    '`update()` did not return an object instance.'
                )
            else:
                self.instance = self.create(validated_data)
                assert self.instance is not None, (
                    '`create()` did not return an object instance.'
                )
            单局部改: 前台提交字典,根据pk一个数据,接口/books/(pk)/
            群局部改: 前台提交列表套字典, 接口 /books/ 注每一个字典都可以通过pk添加
            """
            # 单改,将获取的json数据,通过获取pk对应数据库对象记录,进行修改数据
            pk = kwargs.get("pk")
            request_data = request.data
    
            print(request_data)
            print(pk)
    
            if pk:
                try:
                    book_obj = models.Book.objects.get(pk=pk)
                except:
                    return APIResponse(1, 'pk error')
                # 局部修改就是在整体修改基础上设置partial=True,将所有参与反序列化字段设置为required=False
                book_ser = BookSerializers(instance=book_obj, data=request_data, partial=True)
                book_ser.is_valid(raise_exception=True)
                book_obj = book_ser.save()
                return APIResponse(results=BookSerializers(book_obj).data)
            else:  # 群改
                if not isinstance(request_data, list) or len(request_data) == 0:
                    return APIResponse(1, "data error", http_status=400)
    
                # [{pk:1,...}, {pk:3,...}, {pk:100,...}] => [obj1, obj3, obj100] + [{...}, {...}, {...}]
                # 要考虑pk对应的对象是否被删,以及pk没有对应的对象
                # 假设pk3被删,pk100没有 => [obj1] + [{...}]
    
                # 注: 一定不要在循坏体重对循坏对象进行增删(影响对象的长度的操作
    
                obj_list = []
                data_list = []
    
                for dic in request_data:
                    try:
                        pk = dic.pop("pk")
                        try:
                            obj = models.Book.objects.get(pk=pk, is_delete=False)
                            # 获取对象是否存在
                            obj_list.append(obj)
                            # 添加数据
                            data_list.append(dic)
                        except:
                            pass
                    except:
                        return APIResponse(1, "data error", http_status=400)
                #                          修改的对象列表     对应的修改的数据 多条
                book_ser = BookSerializers(instance=obj_list, data=data_list, many=True, partial=True)
                # 校验数据
                book_ser.is_valid(raise_exception=True)
                book_list_obj = book_ser.save()
                # 返回序列化修改的数据
                return APIResponse(results=BookSerializers(book_list_obj, many=True).data)
    
    

    总结:

    1. 单局部改和群局部改每个字段必须填,
    2. 没有提供整体改的方法需要自定义类继承ListSerializer类重写update方法,需要在子类进行绑定list_serializer_class = BookListSerializers
    3. 单局部改传参BookSerializers(initial=book_obj, data=request_data,partial=True)
    4. 单局部改BookSerializers(instance=obj_list,data=data_list, many=True,partial=True)
    5. 单局部改,序列化类参数instance=修改的对象, data=修改的数据, partial=是否能局部修改,单整体修改就是partial=False(默认就是False)

    八、子序列化

    class PublishModelSerializer(serializers.ModelSerializer):
        class Meta:
            models = models.Publish
            fields = ["name", "addr"]
    
    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            list_serializer_class = BookListSerializers
            model = models.Book
            # 1.多表连查
    
            # fields = ("name", "price", "publish_name", "author_list", 'publish', 'author')
            # 子序列化都是提供给外键(正向方向)完成深度查询的,外键数据是唯一:many=False;不唯一:many=True
            # 注:只能参与序列化,且反序列化不能写(反序列化外键字段会抛异常)
            # # 前提:如果只有查需求的接口,自定义深度还可以用子序列化方式完成
            publish = PublishModelSerializer(many=True)
            fields = ("name", "price", "publish")
    
    class BookAPIView(APIView):
        """
            单查:前台数据为pk,接口为 /books/(pk)/
            群查:前台数据为pks,接口为 /books/
            过滤删除的字段
        """
    
        # # 单查和群查
        def get(self, request, *args, **kwargs):
    
            pk = kwargs.get("pk")
            if pk:
                # 单查
                book_obj = models.Book.objects.filter(pk=pk, is_delete=False).first()
                # 判断
                if not book_obj:
                    return APIResponse(status=1, msg='get error', http_status=400)
                # 返回数据
                book_data = BookSerializers(book_obj).data
                return APIResponse(results=book_data)
            else:
                # 群查
                book_obj = models.Book.objects.filter(is_delete=False).all()
                book_list_data = BookSerializers(book_obj, many=True).data
                return APIResponse(0, "ok", results=book_list_data)
    

    总结:

    1. 子序列化都是提供给外键(正向方向)完成深度查询的,外键数据是唯一:many=False;不唯一:many=True
    2. 只能参与序列化,且反序列化不能写(反序列化外键字段会抛异常)
    3. 如果只有查需求的接口,自定义深度还可以用子序列化方式完成
  • 相关阅读:
    小程序实现删除列表某条内容的功能
    关于多行文本 textarea 在ios 真机上padding相对安卓较大问题
    关于小程序 input 组件内容显示不全(显示的长度不满 input 宽度)问题
    关于小程序button控件上下边框的显示和隐藏问题
    关于微信小程序 textarea组件在fixed定位的模块中随页面移动问题
    首记
    java >>> 和 >>>=的区别
    Nginx" upstream prematurely closed connection while reading response header from upstream"问题排查
    nginx配置rewrite总结
    nginx配置location总结
  • 原文地址:https://www.cnblogs.com/xiongchao0823/p/11923853.html
Copyright © 2020-2023  润新知