序列化器之多表增删改查

一、模型

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':'删除成功'})
posted @ 2020-07-13 18:47  lxttt521  阅读(257)  评论(0编辑  收藏  举报