zoukankan      html  css  js  c++  java
  • Django-rest Framework(五)

    把十大接口做完了才能更好的了解后面的视图类

    1.(重点)二次封装Response;自定义APIResponse继承Response,重写 ____init____方法

    from rest_framework.response import Response  #导入Response类
    
    class APIResponse(Response):  #继承Response类
        def __init__(self,status=0,msg='ok',results=None,http_status=None,headers=None,exception=None,**kwargs): #重写__init__方法
            data = {
                'status':status,
                'msg':msg
            }
            if results is not None:
                data['result'] = results
    
            data.update(**kwargs)   #接收其他多余参数
            # 再使用父类的__init__方法
            super().__i
    

    2.(正常)在orm的模型表中,设置了abstract为True的模型类,称之为基类,这样的模型类是专门作为基类来提供公有属性的(基类不会参与数据迁移)

    class BaseModel(models.Model):   #继承基础模型类
        is_delete = models.BooleanField()  #创建公共属性
        create_time = models.DateTimeField(auto_now_add=True)  #创建公共属性
        class Meta:
            abstract:True   # 声明为基类
            
    class xxx(BaseModel)  # 其他类继承基类
        
    

    3.(重点)ORM多表关联操作(以书籍表 作者表 出版社表 作者详情表为例):

    1. 外键所放的位置

      1. 一对多 : 外键放在多的那一方(出版社,书籍)

        class Book(BaseModel):
            name = models.CharField(max_length=32)
            price = models.DecimalField(max_digits=9,decimal_places=2)
            '''
                 related_name='books' : 设置反向查询为books
                 db_constraint=False : 断开外键约束
                 on_delete=models.DO_NOTHING(在外键数据没有的情况下,任然保持数据 出版社没了,书还是		  那个出版社出版)
            ''' publish=models.ForeignKey(to='Publish',related_name='books',db_constraint=False,on_delete=models.DO_NOTHING)
            # 多对多字段 断约束  设置反向查询名字
            author = models.ManyToManyField(to='Author',db_constraint=False,related_name='books')
            
        class Publish(BaseModel):
            name = models.CharField(max_length=32)
            addres = models.CharField(max_length=32)
        
      2. 多对多:外键放在常用的一方(书 ,作者)

        class Book(BaseModel):
            name = models.CharField(max_length=32)
            price = models.DecimalField(max_digits=9,decimal_places=2)
            '''
                 related_name='books' : 设置反向查询为books
                 db_constraint=False : 断开外键约束
                 on_delete=models.DO_NOTHING(在外键数据没有的情况下,任然保持数据 出版社没了,书还是那个出版社出版)
            '''
            publish = 									models.ForeignKey(to='Publish',related_name='books',db_constraint=False,on_delete=models.DO_NOTHING)
            # 多对多字段 断约束  设置反向查询名字
        author=models.ManyToManyField(to='Author',db_constraint=False,related_name='books')
        
        

      3.一对一 : 外键放在不长用的那一方

      class Book(BaseModel):
          name = models.CharField(max_length=32)
          price = models.DecimalField(max_digits=9,decimal_places=2)
          '''
               related_name='books' : 设置反向查询为books
               db_constraint=False : 断开外键约束
               on_delete=models.DO_NOTHING(在外键数据没有的情况下,任然保持数据 出版社没了,书还是那个			出版社出版)
          '''
          publish = models.ForeignKey(to='Publish',related_name='books',db_constraint=False,on_delete=models.DO_NOTHING)
          # 多对多字段 断约束  设置反向查询名字
          author = models.ManyToManyField(to='Author',db_constraint=False,related_name='books')
      
      
      

      外键字段为正向查询字段,related_name是反向查询字段

    2.如何断外键关联

    ​ 设置外键字段db_constraint=False

    3.外键之间的级联关系

    1. 一对一 : 作者没了,详情也没了 : on_delete=models.CASEADE
    2. 一对多 : 出版社没了,书还是那个出版社出版:on_delete=models.DO_ONTHING
    3. 一对多 : 部门没了 ,员工没有部门(空部门) :null=True ,on_delete=models.SET_NULL
    4. 一对多 : 部门没了,员工进入默认部门(默认值) : default=0, on_delete=models.SET_DEFAULT
    5. 多对多 : 不能设置 on_delete

    4.(重点)连表序列化,在model类中定义插拔序列化方法属性,完成连表查询

        @property
        def author_detail(self):
            author_queryset = self.authors.all()   #查询出所有的作者
            author_detail = []
            for author_obj in author_queryset:
                author_detail.append(
                    {
                        'name': author_obj.name,
                        'sex':author_obj.get_sex_display(),
                        'mobile':author_obj.detail.mobile
    
                    }
                )
            return author_detail  #返回作者列表信息
    

    5.(正常) 子序列化可以辅助快速实现自定义外键深度的序列化,但是不能完成反序列化

    
    # 前提 : 如果只有查需求的接口,自定义深度还可以用子序列化方式完成
    class PublishSerilizer(ModelSerializer):
        # 子序列化都是提供外键(正方向)完成深度查询的,外键数据是唯一:many=Falise 不唯一 many=True
        #注 : 只能参与序列化,且反序列化不能写(反序列化外键字段会抛异常)
        books = BookSerializer(many=True)
        class Meta:
            model = models.Publish
            fields = ['name','address','books']
    

    6.(重要) 单查 群查接口,序列化类提供序列化对象,many参数控制着操作的数据是一条还是多条

    7.(正常)单删 群删接口,后台操作删除字段即可,前端提供pk为单删,提供pks就是群删

    # 单删 群删
        def delete(self,request,*args,**kwargs):
            pk = kwargs.get('pk')
            if pk:
                pks = [pk]
            else:
                pks = request.data.get('pks')
            row = models.Book.objects.filter(is_delete=False,pk__in=pks).update(is_delete=True)
            if row:
                return APIResponse.APIResponse(msg='delete ok')
            return APIResponse.APIResponse(status=1,msg='delete error')
    

    8.(重点) 单增群增接口,根据数据判断是单增还是群增,对应序列化类要设置many,而序列化只需要通过data即可

    # 单增 群增
        def post(self,request,*args,**kwargs):
            request_data = request.data
            if isinstance(request_data,dict)  and len(request_data) !=0:
                book_ser = Serializers.BookSerializer(data=request_data,many=False)
                if book_ser.is_valid(raise_exception=True):
                    book_obj = book_ser.save()
                    return APIResponse.APIResponse(results=Serializers.BookSerializer(book_obj,many=False).data)
                else:
                    return APIResponse.APIResponse(results=book_ser.errors)
    
            elif isinstance(request_data,list) and len(request_data) !=0:
                book_ser = Serializers.BookSerializer(data=request_data, many=True)
                if book_ser.is_valid(raise_exception=True):
                    book_obj_list = book_ser.save()
                    return APIResponse.APIResponse(results=Serializers.BookSerializer(book_obj_list,many=True).data)
                else:
                    return APIResponse.APIResponse(results=book_ser.errors)
            else:
                return APIResponse.APIResponse(1,'add error')
    
    

    9.(正常)单整体改群整体改,前端提供的数据,后台要转化成要修改的对象们和用来更新的数据们,ModelSerializser设置 list_serializesr_class关联自己的ListSerializer,重新update()方法,完成群该

    # 单整体改  群整体改
        def put(self,request,*args,**kwargs):
            request_data = request.data
            pk = kwargs.get('pk')
            if pk:
                try:
                    book_obj = models.Book.objects.get(pk=pk)
                    print(pk)
                    print(book_obj)
                except:
                    return APIResponse.APIResponse(1,'update error')
                book_ser = Serializers.BookSerializer(instance=book_obj,data=request_data)
                book_ser.is_valid(raise_exception=True)
                res_obj = book_ser.save()
                return APIResponse.APIResponse(results=Serializers.BookSerializer(res_obj).data)
            elif isinstance(request_data,list) and len(request_data) !=0:
                obj_list = []
                data_list = []
                for dic in request_data:
                    try:
                        pk = dic.pop('pk')
                        try:
                            obj = models.Book.objects.filter(pk=pk).first()
                            obj_list.append(obj)
                            data_list.append(dic)
                        except:
                            pass
                    except:
                        return APIResponse.APIResponse(1,'update error')
    
                book_ser_list = Serializers.BookSerializer(instance=obj_list,data=data_list,many=True)
                book_ser_list.is_valid(raise_exception=True)
                book_res_list = book_ser_list.save()
                return APIResponse.APIResponse(results=Serializers.BookSerializer(book_res_list,many=True).data)
            else:
                return APIResponse.APIResponse(http_status=400,status=1,msg='update error')
    
    

    10.(正常) 单局部改,序列化参数instance=修改的对象,data=修改的数据,partial=能否能局部修改,单整体改就是partial=False (默认就是False)

    # 单局部改  群局部改
        def patch(self, request, *args, **kwargs):
            request_data = request.data
            pk = kwargs.get('pk')
            if pk:
                try:
                    book_obj = models.Book.objects.get(pk=pk)
                except:
                    return APIResponse.APIResponse(1, 'update error')
                book_ser = Serializers.BookSerializer(instance=book_obj, data=request_data,partial=True)
                book_ser.is_valid(raise_exception=True)
                res_obj = book_ser.save()
                return APIResponse.APIResponse(results=Serializers.BookSerializer(res_obj).data)
            elif isinstance(request_data, list) and len(request_data) != 0:
                obj_list = []
                data_list = []
                for dic in request_data:
                    try:
                        pk = dic.pop('pk')
                        try:
                            obj = models.Book.objects.filter(pk=pk).first()
                            obj_list.append(obj)
                            data_list.append(dic)
                        except:
                            pass
                    except:
                        return APIResponse.APIResponse(1, 'update error')
    
                book_ser_list = Serializers.BookSerializer(instance=obj_list, data=data_list, many=True,partial=True)
                book_ser_list.is_valid(raise_exception=True)
                book_res_list = book_ser_list.save()
                return APIResponse.APIResponse(results=Serializers.BookSerializer(book_res_list, many=True).data)
            else:
                return APIResponse.APIResponse(http_status=400, status=1, msg='update error')
    
    

    异常模块代码:

    
    from rest_framework.response import Response  #导入Response类
    
    class APIResponse(Response):  #继承Response类
        def __init__(self,status=0,msg='ok',results=None,http_status=None,headers=None,exception=None,**kwargs): #重写__init__方法
            data = {
                'status':status,
                'msg':msg
            }
            if results is not None:
                data['result'] = results
    
            data.update(**kwargs)   #接收其他多余参数
            # 再使用父类的__init__方法
            super().__init__(data=data,status=http_status,headers=headers,exception=exception)
    
    

    orm models代码:

    from django.db import models
    from django.conf import settings
    
    
    # 一、基表
    # Model类的内部配置Meta类要设置abstract=True,这样的Model类就是用来作为基表
    # 多表:Book,Publish,Author,AuthorDetail
    class BaseModel(models.Model):
        is_delete = models.BooleanField(default=False)
        create_time = models.DateTimeField(auto_now_add=True)
        class Meta:
            # 基表必须设置abstract,基表就是给普通Model类继承使用的,设置了abstract就不会完成数据库迁移完成建表
            abstract = True
    
    class Book(BaseModel):
        name = models.CharField(max_length=16)
        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,如果想设置关系表级联,只能手动定义关系表
        authors = models.ManyToManyField(to='Author', related_name='books', db_constraint=False)
        @property
        def author_detail(self):
            author_queryset = self.authors.all()
            author_detail = []
            for author_obj in author_queryset:
                author_detail.append(
                    {
                        'name': author_obj.name,
                        'sex':author_obj.get_sex_display(),
                        'mobile':author_obj.detail.mobile
    
                    }
                )
            return author_detail
        class Meta:
            verbose_name_plural = '书籍表'
    
        def __str__(self):
            return self.name
    
    
    class Publish(BaseModel):
        name = models.CharField(max_length=16)
        address = models.CharField(max_length=64)
    
        class Meta:
            verbose_name_plural = '出版社表'
    
        def __str__(self):
            return self.name
    
    class Author(BaseModel):
        name = models.CharField(max_length=16)
        sex = models.IntegerField(choices=[(0, '男'),(1, '女')], default=0)
    
        class Meta:
            verbose_name_plural='作者表'
    
        def __str__(self):
            return self.name
    
    class AuthorDetail(BaseModel):
        mobile = models.CharField(max_length=11)
        # 有作者可以没有详情,删除作者,详情一定会被级联删除
        # 外键字段为正向查询字段,related_name是反向查询字段
        author = models.OneToOneField(to='Author', related_name='detail', db_constraint=False, on_delete=models.CASCADE)
    
    
    
    

    序列化代码:

    from rest_framework import serializers
    from rest_framework.serializers import ModelSerializer
    from . import models
    
    class BookListSerializer(serializers.ListSerializer):
    
        def update(self, instance, validated_data):
            return [
                self.child.update(instance[i],attrs) for i,attrs in validated_data
            ]
    
    class BookSerializer(ModelSerializer):
        class Meta:
            model = models.Book
            list_serializes_class = BookListSerializer
            fields = ['name','price','author_detail','publish','authors']
            extra_kwargs = {
                'publish':{
                    'write_only':True
                },
                'authors':{
                    'write_only':True
                }
            }
    
    class PublishSerilizer(ModelSerializer):
        books = BookSerializer(many=True)
        class Meta:
            model = models.Publish
            fields = ['name','address','books']
    
  • 相关阅读:
    【Flask-RESTPlus系列】Part3:请求解析
    【Flask-RESTPlus系列】Part2:响应编组
    【Flask-RESTPlus系列】Part1:快速入门
    webpack中hash、chunkhash、contenthash区别
    如何将现有 git 仓库中的子项目单独抽出来作为一个独立仓库并保留其提交历史
    Using Immutable in React + React-Redux
    ChromeExtension那些事儿
    Get started with Google Analytics
    middlewares in GCC
    实现一个简单的虚拟DOM
  • 原文地址:https://www.cnblogs.com/kuck/p/11921937.html
Copyright © 2011-2022 走看看