首页 > 技术文章 > -drf-基于book表的多表群操作

arher 2020-11-17 18:13 原文

准备

# 注意:以后所有的数据删除,尽量用软删除,使用一个字段标识是否删除,而不是真正的从数据库中删除,
# 即软删除后的数据不可查
	-好处:1.这样删除数据不会影响索引,不会导致索引失效
  			2.之前存的用户数据还在,已备以后使用
    
# 表模型如下
# 抽象出一个基表(不在数据库生成,abstract=True),只用来继承

from django.db import models
from django.contrib.auth.models import AbstractUser
from datetime import datetime
class BaseModel(models.Model):
    is_delete = models.BooleanField(default=False)
    # 默认没有被软删除
    class Meta:
        # 基表必须设置abstract,基表就是给普通Model类继承使用的,设置了abstract就不会完成数据库迁移完成建表
        abstract = True

class UserInfo(AbstractUser,BaseModel):
    mobile = models.BigIntegerField(unique=True, null=True)
    icon = models.FileField(upload_to='avatar', default='avatar/default.jpg')


class Book(BaseModel):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    publish_date = models.DateField(auto_now_add=True)  # 注册时间,不会因为更新操作而改变
    # 一对多
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    # 多对多
    authors = models.ManyToManyField(to='Author')

    @property
    def publish_name(self):
        return self.publish.name

    @property
    def author_list(self):
        return [{'name': author.name, 'sex': author.get_sex_display()} for author in self.authors.all()]


class Publish(BaseModel):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)


class Author(BaseModel):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    sex = models.IntegerField(choices=[(0, '男'), (1, '女')], default=0)

url配置

    path('book/', views.BookInfo.as_view()),
    re_path('book/(?P<pk>\d+)/', views.BookInfo.as_view())

序列化器

class ListBookSerializer(serializers.ListSerializer):
    def create(self, validated_data):
        return [self.child.create(data) for data in validated_data]
        # 相当于调用了子元素中的序列化器的create方法

    def update(self, instance, validated_data):
        print(instance)  # 图书对象集
        print(validated_data)  # 列表套字典是要修改的
        return [self.child.update(book, validated_data[i]) for i, book in enumerate(instance)] # 调用了list的序列化器进行了update方法,索引标识了更新的是list里面的那个序列化器对象


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        list_serializer_class = ListBookSerializer # 当进行many=True的群操作时,自动转到List序列化器
        fields = '__all__'

1 单增群增

class BookInfo(APIView):
    def post(self, request):
        if isinstance(request.data, dict):
            # 如果是字典则是单独的一个数据
            ser = seralizer.BookSerializer(data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(data=ser.data)

        elif isinstance(request.data, list):
            # 列表套字典标识多个数据
            ser = seralizer.BookSerializer(data=request.data, many=True)
            # 内部如何实现?
            # many=True,ser不是BookSerializer对象,而是ListSerializer对象,套了一个个的BookSerializer
            ser.is_valid(raise_exception=True)
            ser.save()  # ListSerializer的save
            return APIResponse(msg='增加%s条成功' % len(request.data))

2 单查群查

class BookInfo(APIView):
    def get(self, request, *args, **kwargs):
        pk = kwargs.get('pk', None)
        # 由于在空字典取值会报错,需要默认取None
        if pk:
            book = models.Book.objects.get(id=pk, is_delete=False)  # 如果没有被软删除可以查
            ser = seralizer.BookSerializer(instance=book)
        else:
            book_list = models.Book.objects.all().filter(is_delete=False)
            ser = seralizer.BookSerializer(instance=book_list, many=True)
        return APIResponse(data=ser.data)

3 单改群改

class BookInfo(APIView):
    def put(self, request, *args, **kwargs):
        pk = kwargs.get('pk', None)
        print(pk)
        if pk:
            # 单条修改
            book = models.Book.objects.filter(id=pk, is_delete=False)
            ser = seralizer.BookSerializer(instance=book, data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(msg='修改成功')
        else:
            # 群改
            pks = []
            # 列表套字典的数据格式
            for item in request.data:
                pks.append(item['id'])  # 弹出id并写入pks中,不需要改id
                item.pop('id')
            print(pks)
            book_list = models.Book.objects.filter(id__in=pks, is_delete=False)
            ser = seralizer.BookSerializer(instance=book_list, data=request.data, many=True)
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(msg='修改%s条成功' % len(pks))

4 单删群删

class BookInfo(APIView):
    def delete(self, request, *args, **kwargs):
        pk = kwargs.get('pk', None)
        pks = []
        print(pk)
        if pk:
            # 单条删除
            pks.append(pk)

        else:
            pks = request.data

        res = models.Book.objects.filter(id__in=pks).update(is_delete=True)
        # 软删除即可
        if res:
            return APIResponse(msg='删除%s条成功' % res)
        else:
            return APIResponse(code=999, msg='没有要删除的数据')

推荐阅读