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':'删除成功'})
    
  • 相关阅读:
    JAVA基础--JAVA API常见对象(包装类和正则)12
    编程中最没用的东西是源代码,最有用的东西是算法和数据结构(转载)
    angularjs calling order
    Service vs provider vs factory 转自:http://stackoverflow.com/questions/15666048/service-vs-provider-vs-factory
    构建自己的AngularJS,第一部分:作用域和digest 转摘:http://www.ituring.com.cn/article/39865
    angularjs 信息链接 转摘自:http://www.zhihu.com/question/27427447
    activity 生命周期 http://stackoverflow.com/questions/8515936/android-activity-life-cycle-what-are-all-these-methods-for
    google+ sign in and get the oauth token 转摘:https://gist.github.com/ianbarber/5170508
    谁动了我的内存:php内存泄露,系统缓存消耗? 转摘:http://blog.csdn.net/tao_627/article/details/9532497
    installing-sql-server-2012-error-prior-visual-studio-2010-instances-requiring 转摘
  • 原文地址:https://www.cnblogs.com/hz2lxt/p/13295023.html
Copyright © 2011-2022 走看看