zoukankan      html  css  js  c++  java
  • 序列化器之多表增删改查

    一、模型

    from django.db import models
    
    # Create your models here.
    class Basemodel(models.Model):
        create_time = models.DateTimeField(auto_now_add=True)
        last_update_time = models.DateTimeField(auto_now=True)
        is_delete = models.BooleanField(default=False)
    
        class Meta:
            # 表示这个表是虚拟表,不会再数据库中创建
            abstract = True
    
    class Book(Basemodel):
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5,decimal_places=2)
        # db_constraint = False 表示外键关联实际断开,只有逻辑连接
        publish = models.ForeignKey(to='Publish',on_delete=models.DO_NOTHING,db_constraint=False)
        authors = models.ManyToManyField(to='Author',db_constraint=False)
        class Meta:
            verbose_name_plural = '书表'
        @property
        def publish_name(self):
            return self.publish.name
        def authors_list(self):
            # 返回一个作者列表,内部放作者的所有信息[{id:pk,'name':name}]
            authors_list = self.authors.all()
            return [{'id':author.id,'name':author.name,'phone':author.author_detail.phone} for author in authors_list]
    
        def __str__(self):
            return self.name
    
    
    class Author(Basemodel):
        name = models.CharField(max_length=32)
        sex = models.IntegerField(choices=((1,'男'),(2,'女'),(3,'其他')))
        author_detail = models.OneToOneField(to='Author_detail',on_delete=models.CASCADE,db_constraint=False)
        class Meta:
            verbose_name_plural = '作者表'
        def __str__(self):
            return self.name
    
    class Author_detail(Basemodel):
        phone = models.IntegerField()
    
    class Publish(Basemodel):
        name = models.CharField(max_length=32)
        addr = models.CharField(max_length=32)
    
        class Meta:
            verbose_name_plural = '出版社表'
        def __str__(self):
            return self.name
    # 二、表断关联
    # 1、表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
    # 2、断关联后不会影响数据库查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
    # 3、断关联一定要通过逻辑保证表之间数据的安全,不要出现脏数据,代码控制
    # 4、断关联
    # 5、级联关系
    #       作者没了,详情也没:on_delete=models.CASCADE
    #       出版社没了,书还是那个出版社出版:on_delete=models.DO_NOTHING
    #       部门没了,员工没有部门(空不能):null=True, on_delete=models.SET_NULL
    #       部门没了,员工进入默认部门(默认值):default=0, on_delete=models.SET_DEFAULT
    

    二、序列化器

    from rest_framework import serializers
    from app01 import models
    
    class New_update_ListSerializer(serializers.ListSerializer):
        # 重写update方法,用来实现群改的效果
        def update(self, instance, validated_data):
            return [self.child.update(instance[i],data) for i,data in enumerate(validated_data)]
    
    class Bookserializers(serializers.ModelSerializer):
        # 如果要在book表中找到其他表的数据有两种方法
        # 方案一、通过source(只能序列化,反序列化出问题)
        # publish=serializers.CharField(source='publish.name')
        # 方案二、在models中Book表内写获取对应数据的方法
        class Meta:
            # 父类中会自动把New_update_ListSerializer替代ListSerializer
            list_serializer_class = New_update_ListSerializer
            model = models.Book
            # 针对序列化字段和反序列化字段用不同的方式表示
            fields = ('id','name','price','authors','publish_name','publish','authors_list')
            extra_kwargs = {
                'id':{'read_only':True},
                'authors':{'write_only':True},
                'publish': {'write_only':True},
                'publish_name': {'read_only':True},
                'authors_list': {'read_only':True},
            }
    

    三、视图

    1 单增群增

    class BookAPIView(GenericAPIView):
        queryset = models.Book.objects.filter(is_delete=False)
        serializer_class = sers.Bookserializers
        def get(self,request,*args,**kwargs):
            pk = kwargs.get('pk')
            if pk:
                book_ser = self.get_serializer(self.queryset.filter(pk=pk).first())
                return Response(book_ser.data)
            else:
                book_ser = self.get_serializer(self.queryset.all(),many=True)
                return Response(data=book_ser.data)
    

    2 单存群存

        def post(self,request,*args,**kwargs):
            if isinstance(request.data,dict):
                book_ser = self.get_serializer(data=request.data)
                return Response(book_ser.data)
            elif isinstance(request.data,list):
                book_ser = self.get_serializer(data=request.data,many=True)
    
            book_ser.is_valid(raise_exception=True)
            # 新增---》ListSerializer--》create方法
            # def create(self, validated_data):
            #   self.child是BookModelSerializer对象
            #   print(type(self.child))
            #     return [
            #         self.child.create(attrs) for attrs in validated_data
            #     ]
            book_ser.save()
            return Response(book_ser.data)
    
    

    3 单改群改

        # 在提交数据之前,需要确定好数据的格式,需要和前端人员协商
        def put(self,request,*args,**kwargs):
            id = kwargs.get('pk')
            if id:
                book_ser = self.get_serializer(self.queryset.filter(pk=id).first(),data=request.data)
                book_ser.is_valid(raise_exception=True)
                book_ser.save()
                return Response(book_ser.data)
            else:
                # 方式一:传入的数据是[{id:1,xxx}] 循环取出id一条一条修改(常用)
                # l = []
                # for book in request.data:
                #     id = book.pop('id')
                #     book_ser = self.get_serializer(self.queryset.filter(id=id).first(),data=book)
                #     book_ser.is_valid(raise_exception = True)
                #     book_ser.save()
                #     l.append(book_ser.data)
                # return Response(l)
                # 方式二:通过重写ListSerializer的update方法(不常用)
            # 因为我在通过序列化的时候传入many=True,这个时候实例化的类是ListSerializer,我们可以看看它内部的源码
            # 得知它写了create方法,也就是我们可以支持群增,但是update的方法是直接抛异常的,也就是我们要使用就必须重写这个方法
            # 但是如何让我们重写的类(继承ListSerializer)去替换ListSerializer在序列化中的地位呢?
            # 查看ListSerializer父类的__new__方法
            #     def __new__(cls, *args, **kwargs):
            #         # We override this method in order to automagically create
            #         # `ListSerializer` classes instead when `many=True` is set.
            #         if kwargs.pop('many', False):
            #             return cls.many_init(*args, **kwargs)
            #         return super().__new__(cls, *args, **kwargs)
                # 如果在实例化的时候传了many=True,那就调用many_init方法
                # 而这个方法的最后有这么两句话
                # meta = getattr(cls, 'Meta', None)
                # list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
                # 看看我们自己写的类中有没有Meta类,如果有的话,再看看里面有没有list_serializer_class的赋值
                # 如果有的话,这个值对应的类名就代替ListSerializer的地位
                # 所以在此我们在class Meta中给他一个参数list_serializer_class= 我们自己重写的类即可
                id_list = []
                for book in request.data:
                    id_list.append(book.get('id'))
                book_ser = self.get_serializer(self.queryset.filter(id__in = id_list),request.data,many=True)
                book_ser.is_valid(raise_exception = True)
                book_ser.save()
                return Response(book_ser.data)
    

    4 单删群删

        def delete(self,request,**kwargs):
            id = kwargs.get('pk')
            if id:
                obj = self.queryset.filter(id=id).update(is_delete = True)
                if obj:
                    return Response({'msg':'删除成功'})
                else:
                    return Response({'msg':'目标不存在'})
            else:
                # request.data = [1,2,3]
                obj = self.queryset.filter(id__in = request.data).update(is_delete = True)
                return Response({'msg':'删除成功'})
    
  • 相关阅读:
    POJ 1401 Factorial
    POJ 2407 Relatives(欧拉函数)
    POJ 1730 Perfect Pth Powers(唯一分解定理)
    POJ 2262 Goldbach's Conjecture(Eratosthenes筛法)
    POJ 2551 Ones
    POJ 1163 The Triangle
    POJ 3356 AGTC
    POJ 2192 Zipper
    POJ 1080 Human Gene Functions
    POJ 1159 Palindrome(最长公共子序列)
  • 原文地址:https://www.cnblogs.com/hz2lxt/p/13295023.html
Copyright © 2011-2022 走看看