drf—— Book系列连表接口

注意:

# 注意:以后所有的数据删除,尽量用软删除,使用一个字段标志是否删除,而不是真正的从数据库中删除
    -好处:1 这样删除数据不会影响索引,不会导致索引失效
          2 之前存的用户数据还在,以备以后使用

models.py--->数据迁移

# 抽象出一个基表(不再数据库生成,abstract=True),只用来继承

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', 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 publish_name(self):
        return self.publish.name
    @property
    def author_list(self):
        # ll=[]
        # for author in self.authors.all():
        #     ll.append({'name':author.name,'sex':author.get_sex_display()})
        return [{'name': author.name, 'sex': author.get_sex_display()} for author in self.authors.all()]


class Publish(BaseModel):
    name = models.CharField(max_length=16)
    address = models.CharField(max_length=64)


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


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)

admin.py

from django.contrib import admin
from app01 import models

admin.site.register(models.Book)
admin.site.register(models.Publish)
admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)

创建一个超级用户,登录admin后台管理,造出一些数据(books ,authors,publish)

serializer.py

# 图书表序列化类

from app01 import models
from rest_framework import serializers

class ListBookSerializer(serializers.ListSerializer):
    # def create(self, validated_data):
    #     print('=======',validated_data)
    #     return '1'
    def update(self, instance, validated_data):
        print(instance) # book_list:是一堆图书对象
        print(validated_data) # 列表套字典,是要修改的数据

        return [self.child.update(book, validated_data[i]) for i, book in enumerate(instance)]


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        list_serializer_class=ListBookSerializer # 指定many=True的时候,生成的ListBookSerializer的对象了
        fields = ['name', 'price', 'publish', 'authors', 'publish_name', 'author_list']
        extra_kwargs = {
            'publish': {'write_only': True},
            'authors': {'write_only': True},
            'publish_name': {'read_only': True},
            'author_list': {'read_only': True},

        }

    # def create(self, validated_data):
    #     print(validated_data)

utils.py

from rest_framework.response import Response

class APIResponse(Response):
    def __init__(self, code=100, msg='成功', data=None, status=None,
                 headers=None, content_type=None, **kwargs):
        dic = {'code': code, 'msg': msg}
        if data:
            dic['data'] = data
        dic.update(kwargs)
        super().__init__(data=dic, status=status, headers=headers, content_type=content_type)


from rest_framework.views import exception_handler


def common_exception(exc, context):
    # 先调用REST framework默认的异常处理方法获得标准错误响应对象
    response = exception_handler(exc, context)
    # 在此处补充自定义的异常处理
    if response is None:
        response = Response(data={'code':999,'msg':str(exc)})

    return response

settings.py

INSTALLED_APPS = [
    ...
    'rest_framework'
]

REST_FRAMEWORK = {
    # 配置全局异常
    'EXCEPTION_HANDLER': 'app01.utils.common_exception'
}

views.py

# book表单增群增
from app01 import serializer
from app01 import models
from rest_framework.views import APIView
from app01.utils import APIResponse


class BookView(APIView):
    def post(self, request, *args, **kwargs):
        if isinstance(request.data, dict):
            # 增一条
            ser = serializer.BookSerializer(data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(data=ser.data)
        elif isinstance(request.data, list):
            # 增多条(让many=True就可以了)
            ser = serializer.BookSerializer(data=request.data, many=True)
            # 内部如何实现的?
            # many=True,ser不是BookSerializer对象,而是ListSerializer对象,套了一个个的BookSerializer
            print(type(ser))
            ser.is_valid(raise_exception=True)
            #
            from rest_framework.serializers import ListSerializer
            ser.save()  # ListSerializer的save
            return APIResponse(msg='增加%s条成功' % len(request.data))
    def get(self, request, *args, **kwargs):
        pk = kwargs.get('pk', None)
        if pk:
            # 单查
            # 方式一
            # book=models.Book.objects.filter(id=pk).filter(is_delete=False).first()
            # if not book:
            #     raise Exception('要查询的不存在')

            # 方式二
            book = models.Book.objects.get(id=pk, is_delete=False)
            ser = serializer.BookSerializer(instance=book)

        else:
            # 查所有
            book_list = models.Book.objects.all().filter(is_delete=False)
            ser = serializer.BookSerializer(instance=book_list, many=True)
        return APIResponse(data=ser.data)

    def delete(self, request, *args, **kwargs):
        pk = kwargs.get('pk', None)
        pks = []
        if pk:
            # 单条删除
            # res=models.Book.objects.filter(id=pk).update(is_delete=True)
            # print(res)
            # return APIResponse(msg='删除成功')
            pks.append(pk)
        else:
            pks = request.data

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

    def put(self, request, *args, **kwargs):
        pk = kwargs.get('pk', None)
        if pk:
            # 单条修改
            book = models.Book.objects.get(id=pk, is_delete=False)
            ser = serializer.BookSerializer(instance=book, data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(msg='修改成功')
        else:
            # 分析:ListSerializer的update方法没有写,需要我们自己写
            from rest_framework.serializers import ListSerializer
            # pks=[item['id'] for item in request.data]

            # 如果不重写ListSerializer的update方法,这是存不进去的
            pks = []
            for item in request.data:
                pks.append(item['id'])
                item.pop('id')

            print(request.data)
            book_list = models.Book.objects.filter(id__in=pks, is_delete=False)
            ser = serializer.BookSerializer(instance=book_list, data=request.data, many=True)
            print(type(ser))
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(msg='修改%s条成功')

urls.py

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    ### book表
    path('books/', views.BookView.as_view()),
    re_path('books/(?P<pk>d+)', views.BookView.as_view()),

]
原文地址:https://www.cnblogs.com/guojieying/p/13969245.html