bookserlizer 十大接口

目录

一、导包补充
二、深度查询

  1. 子序列化和depth方法
    (1)什么是子序列化
    (2)all 方法 exclude方法
    (3)子序列化实例
  2. 插拔式
    三、十大接口
  3. 十大接口中注意点(很重要)
  4. 实例
    一、导包补充
    在导包时,如果用from 文件1 import ,则文件1中的以下划线开头的变量,都不能访问。无论是单下划线还是双下线。
    用import 文件1的方式,还是能访问到文件1中以下划线开头的变量,没有影响。
    当我们用from 文件1 import
    的方式导包时,怎么才能访问到其中以下划线开头的变量呢,解决方法如下

    解决方法: 使用 __all__方法将下划线开头的变量储存。

    __all__本来就默认包含普通的变量,所以自己重写__all__时,要把普通变量也加上

例子

文件1中:

x = 10
_y = 20
__z = 30

all = [‘x‘,‘_y‘,‘__z‘]

文件2中

from 文件1 import *

print(x, _y, __z) # 结果: 10 20 30
二、深度查询
深度查询主要是用在:当给前端数据时,要求带有与当前表有关联的其他表的某些数据。通过连表操作,将关联表中的数据一起序列化
外键字段默认显示的是外键值(int类型),不会自己进行深度查询,但配置了深度查询就可以实现将关联的那一个表的字段序列化

深度查询共有3中方式:

子序列化:必须有子序列化类配合,不能反序列化了
depth方法:自动深度查询的是关联表的所有字段,数据量太多
插拔式:@property,方法名字不能与外键名同名

  1. 子序列化和depth方法
    (1)什么是子序列化
    当前序列化类1,与上面的其他序列化类2,通过外键字段相关联,这样当前序列化类序列化时,就会将序列化类2中的配置的序列化字段一同序列化
    进行子序列化,关联变量必须为连表时的 正反向外键字段
    子序列化和depth方法都不常用
    (2)all 方法 exclude方法
    用法见下面的实例
    但__all__ 方法和exclude方法不能同时使用
    (3)子序列化实例

序列化类2

class BookModelSerializer(serializers.ModelSerializer):

class Meta:
    model = models.Book
    fields = ['name', 'price', 'publish', 'authors', 'publish_info', 'author_list']
    extra_kwargs = {
        'publish': {
            'write_only': True
        },
        'authors': {
            'write_only': True
        }
    }

序列化类1

class PublishModelSerializer(serializers.ModelSerializer):
# 子序列化:
# 1)只能在序列化中使用
# 2)字段名必须是外键(正向反向)字段
# 因为自定义序列化字段是默认read_only,是不能参与反序列化的,而子序列化必须为外键名,所以就无法入库
# 3)在外键关联数据记录是多条时,需要明确many=True
# 4)是单向操作,因为作为子系列的类必须写在上方,所以不能产生逆方向的子序列化
books = BookModelSerializer(many=True) # 子序列化关联字段
class Meta:
model = models.Publish
fields = [‘name‘, ‘address‘, ‘books‘]

    # 了解配置
    # fields = '__all__'  # 表示当前模型表的所有字段都参与序列化和反序列化,但这种方法我们不能配置extra_kwargs了。外键字段默认显示的是外键值(int类型),不会自己进行深度查询,但配置了子序列化就可以实现了

    # exclude = ['name']  # 表示出了name字段,该模型表的其他所有字段都参与序列化和反序列化

    # depth = 2  # 自动深度,值代表深度次数 如publis表序列化了外键字段books,没有使用子序列化时,则对应的book数据都会被序列化,这是深度1,若book表有外键字段,也被序列化了,则也会将book表对应另一个的表数据序列化,这是深度2。深度2包含深度1,就是深度值越大,能序列化的关联表层次越多
  1. 插拔式
    名字不能与外键名同名

用哪些字段,就在模型类中定义哪些函数,其返回值就是要序列化的字段的值

实例

models文件中**********************************

class Book(BaseModel):
name = models.CharField(max_length=64)
price = models.DecimalField(max_digits=10, decimal_places=2)
publish = models.ForeignKey(to=‘Publish‘, related_name=‘books‘, db_constraint=False, on_delete=models.DO_NOTHING, null=True)
authors = models.ManyToManyField(to=‘Author‘, related_name=‘books‘, db_constraint=False)

# 自定义插拔式深度查询字段
@property
def publish_info(self):  # 单个数据
    # from .serializers import PublishModelSerializer
    # return PublishModelSerializer(self.publish).data
    return {
        'name': self.publish.name,
        'address': self.publish.address,
    }

# 自定义插拔式深度查询字段
@property
def author_list(self):
    author_list_temp = []  # 存放所有作者格式化成数据的列表
    authors = self.authors.all()  # 所有作者
    for author in authors:  # 遍历处理所有作者
        author_dic = {
            'name': author.name,
        }
        try:  # 有详情才处理详情信息
            author_dic['mobile'] = author.detail.mobile
        except:
            author_dic['mobile'] = '无'

        author_list_temp.append(author_dic)  # 将处理过的数据添加到数据列表中

    return author_list_temp  # 返回处理后的结果

def __str__(self):
    return self.name

自定义的序列化文件中:*******************************

class BookModelSerializer(serializers.ModelSerializer):

class Meta:
    model = models.Book
    fields = ['name', 'price', 'publish', 'authors', 'publish_info', 'author_list']
    extra_kwargs = {
        'publish': {
            'write_only': True
        },
        'authors': {
            'write_only': True
        }
    }    

三、十大接口

  1. 十大接口中注意点(很重要)
    就是get/post/put/patch/delete对应的单操作和群操作,一共对应数据的10种操作。实际的每种资源(book,publish,user等)对应的url各只有两条。
    5大请求方式对应的注意点
    最重要的是,所有群操作中只要有一个数据提供的有误,整个群操作都不会成功。
    下面写的many=True,partial=True都是给序列化类传的关键字参数。partial=True参数的作用是让反序列化的所有字段都变为可选字段(即required=False)。还有一个参数context,它的作用是给序列化类传参。在序列化类中,序列化对象.context 就可以访问到了。
    序列化时要传对象,反序列化时传的是data=request.data(传的是前端提交的数据)。序列化类中包含序列化操作和反序列化操作。
    代码书写中的细节
    1)get:单查群查 => 群查时要有 many=True
    2)post:单增群增 => 群增时要有 many=True
    3)delete:单删群删 => 只做表中is_delete字段的修改,不需要序列化类的参与
    4)put/patch:单改群改 =>

群改时内部其实是用默认的ListSerializer序列化类对多个数据记录进行遍历,再使用ModelSerializer提供的单改的方法轮流修改每个数据记录。(其实ModelSerializer序列化成员内部为我们写好了单增和群增方法,也写好了单改的方法。只有群增没写,需要我们重写update方法。所以群改时:要在相应的序列化类中自定义配置list_serializer_class = 自定义的ListSerializer类,变量名必须是list_serializer_class。在自定义的ListSerializer类中重写update方法,重写的内容就是把群改的对象一个个传入原单改的方法中)

patch方法中要有partial=True,表示反序列化的字段都变成选填字段,提供就修改成提供的,不提供就使用原来的。 其实整体改和局部改的方法差不多,局部改更加简便合理,以后对数据的修改都用patch方法就可以了

5)群操作中,在序列化类中都要传入many=True这个参数。
在群增时,通过many=True来分别,内部是直接新增还是遍历分别新增

在整体改和局部改中,通过many=True和partial=True这两个参数,来区分是整体改还是局部改,通过many=True来执行响应的操作。当many=True时,还需要手动再序列化类中重写群改方法。

6)在进行数据的修改时,实例化序列化对象时,有一个参数为:instance= 要修改的数据对象 。当instance参数有值时,表示下面的save方法进行的是修改操作,当instance参数没值时,表示下面的save方法进行的是新增操作。instance默认是None

7)序列化对象.is_valid(raise_exception=True) # 表示校验是否全部通过,通过这继续往下走,有一个没通过就停止,自动返回异常信息给前端

  1. 实例

    views文件中:***************************************

from rest_framework.views import APIView
from rest_framework.response import Response
from . import models, serializers
from .response import APIResponse

出版社群查

class PublishAPIView(APIView):
def get(self, request, *args, **kwargs):
publish_query = models.Publish.objects.all()
publish_ser = serializers.PublishModelSerializer(publish_query, many=True)
return APIResponse(results=publish_ser.data)

class BookAPIView(APIView):
# 单查群查
def get(self, request, *args, **kwargs):
pk = kwargs.get(‘pk‘)
if pk:
book_obj = models.Book.objects.filter(is_delete=False, pk=pk).first()
book_ser = serializers.BookModelSerializer(book_obj)
else:
book_query = models.Book.objects.filter(is_delete=False).all()
book_ser = serializers.BookModelSerializer(book_query, many=True)
return APIResponse(results=book_ser.data)
# return Response(data=book_ser.data)

# 单删群删
def delete(self, request, *args, **kwargs):
    """
    单删:接口:/books/(pk)/   数据:空
    群删:接口:/books/   数据:[pk1, ..., pkn]
    逻辑:修改is_delete字段,修改成功代表删除成功,修改失败代表删除失败
    """
    pk = kwargs.get('pk')
    if pk:
        pks = [pk]  # 将单删格式化成群删一条
    else:
        pks = request.data  # 群删
    try:  # 数据如果有误,数据库执行会出错
        rows = models.Book.objects.filter(is_delete=False, pk__in=pks).update(is_delete=True)
    except:
        return APIResponse(1, '数据有误')

    if rows:
        return APIResponse(0, '删除成功')
    return APIResponse(1, '删除失败')

# 单增群增
def post(self, request, *args, **kwargs):
    """
    单增:接口:/books/   数据:{...}
    群增:接口:/books/   数据:[{...}, ..., {...}]
    逻辑:将数据给系列化类处理,数据的类型关系到 many 属性是否为True
    """
    if isinstance(request.data, dict):
        many = False
    elif isinstance(request.data, list):
        many = True
    else:
        return Response(data={'detail': '数据有误'}, status=400)

    book_ser = serializers.BookModelSerializer(data=request.data, many=many)
    book_ser.is_valid(raise_exception=True)
    book_obj_or_list = book_ser.save()
    return APIResponse(results=serializers.BookModelSerializer(book_obj_or_list, many=many).data)

# 整体单改群改
def put(self, request, *args, **kwargs):
    """
    单改:接口:/books/(pk)/   数据:{...}
    群增:接口:/books/   数据:[{pk, ...}, ..., {pk, ...}]
    逻辑:将数据给系列化类处理,数据的类型关系到 many 属性是否为True
    """
    pk = kwargs.get('pk')
    if pk:  # 单改
        try:
            # 与增的区别在于,需要明确被修改的对象,交给序列化类
            book_instance = models.Book.objects.get(is_delete=False, pk=pk)
        except:
            return Response({'detail': 'pk error'}, status=400)

        book_ser = serializers.BookModelSerializer(instance=book_instance, data=request.data)
        book_ser.is_valid(raise_exception=True)
        book_obj = book_ser.save()
        return APIResponse(results=serializers.BookModelSerializer(book_obj).data)
    else:  # 群改
        # 分析(重点):
        # 1)数据是列表套字典,每个字典必须带pk,就是指定要修改的对象,如果有一条没带pk,整个数据有误
        # 2)如果pk对应的对象已被删除,或是对应的对象不存在,可以认为整个数据有误(建议),可以认为将这些错误数据抛出即可
        request_data = request.data
        try:
            pks = []
            for dic in request_data:
                pk = dic.pop('pk')  # 解决分析1,没有pk,pop方法就会抛异常
                pks.append(pk)

            book_query = models.Book.objects.filter(is_delete=False, pk__in=pks).all()
            if len(pks) != len(book_query):
                raise Exception('pk对应的数据不存在')
        except Exception as e:
            return Response({'detail': '%s' % e}, status=400)

        book_ser = serializers.BookModelSerializer(instance=book_query, data=request_data, many=True)
        book_ser.is_valid(raise_exception=True)
        book_list = book_ser.save()
        return APIResponse(results=serializers.BookModelSerializer(book_list, many=True).data)

# 局部单改群改
def patch(self, request, *args, **kwargs):
    pk = kwargs.get('pk')
    if pk:  # 单改
        try:
            book_instance = models.Book.objects.get(is_delete=False, pk=pk)
        except:
            return Response({'detail': 'pk error'}, status=400)
        # 设置partial=True的序列化类,参与反序列化的字段,都会置为选填字段
        # 1)提供了值得字段发生修改。
        # 2)没有提供的字段采用被修改对象原来的值

        # 设置context的值,目的:在序列化完成自定义校验(局部与全局钩子)时,可能需要视图类中的变量,如请求对象request
        # 可以通过context将其传入,在序列化校验方法中,self.context就能拿到传入的视图类中的变量
        book_ser = serializers.BookModelSerializer(instance=book_instance, data=request.data, partial=True, context={'request': request})
        book_ser.is_valid(raise_exception=True)
        book_obj = book_ser.save()
        return APIResponse(results=serializers.BookModelSerializer(book_obj).data)
    else:  # 群改
        request_data = request.data
        try:
            pks = []
            for dic in request_data:
                pk = dic.pop('pk')
                pks.append(pk)

            book_query = models.Book.objects.filter(is_delete=False, pk__in=pks).all()
            if len(pks) != len(book_query):
                raise Exception('pk对应的数据不存在')
        except Exception as e:
            return Response({'detail': '%s' % e}, status=400)

        book_ser = serializers.BookModelSerializer(instance=book_query, data=request_data, many=True, partial=True)
        book_ser.is_valid(raise_exception=True)
        book_list = book_ser.save()
        return APIResponse(results=serializers.BookModelSerializer(book_list, many=True).data)

自定义的序列化模块文件中:*********************************

from rest_framework import serializers
from . import models

多表操作

class BookListSerializer(serializers.ListSerializer):
# 自定义的群增群改辅助类,没有必要重写create方法
def create(self, validated_data):
return super().create(validated_data)

def update(self, instance_list, validated_data_list):
    return [
        self.child.update(instance_list[index], attrs) for index, attrs in enumerate(validated_data_list)
    ]

class BookModelSerializer(serializers.ModelSerializer):
# 外键字段默认显示的是外键值(int类型),不会自己进行深度查询
# 深度查询方式:
# 1)子序列化:必须有子序列化类配合,不能反序列化了
# 2)配置depth:自动深度查询的是关联表的所有字段,数据量太多
# 3)插拔式@property:名字不能与外键名同名
class Meta:
# ModelSerializer默认配置了ListSerializer辅助类,帮助完成群增群改
# list_serializer_class = serializers.ListSerializer
# 如果只有群增,是不需要自定义配置的,但要完成群改,必须自定义配置
list_serializer_class = BookListSerializer

    model = models.Book
    fields = ['name', 'price', 'publish', 'authors', 'publish_info', 'author_list']
    extra_kwargs = {
        'publish': {
            'write_only': True
        },
        'authors': {
            'write_only': True
        }
    }

# 验证视图类是否将request请求参数通过context传入
def validate(self, attrs):
    print('传入的request: %s' % self.context.get('request'))
    return attrs

class PublishModelSerializer(serializers.ModelSerializer):
# 子序列化:
# 1)只能在序列化中使用
# 2)字段名必须是外键(正向反向)字段
# 因为相对于自定义序列化外键字段,自定义序列化字段是不能参与反序列化的,而子序列化必须为外键名,所以就无法入库
# 3)在外键关联数据是多条时,需要明确many=True
# 4)是单向操作,因为作为子系列的类必须写在上方,所以不能产生逆方向的子序列化
# books = BookModelSerializer(many=True)
class Meta:
model = models.Publish
fields = [‘name‘, ‘address‘, ‘books‘]

models文件中:*************************************

from django.db import models

Book表:

Publish表:

Author表:

AuthorDetail表:

from django.contrib.auth.models import User
class BaseModel(models.Model):
is_delete = models.BooleanField(default=False)
created_time = models.DateTimeField(auto_now_add=True)

class Meta:
    # 基表,为抽象表,是专门用来被继承,提供公有字段的,自身不会完成数据库迁移
    abstract = True

class Book(BaseModel):
name = models.CharField(max_length=64)
price = models.DecimalField(max_digits=10, decimal_places=2)
publish = models.ForeignKey(to=‘Publish‘, related_name=‘books‘, db_constraint=False, on_delete=models.DO_NOTHING, null=True)
authors = models.ManyToManyField(to=‘Author‘, related_name=‘books‘, db_constraint=False)

# 自定义反序列化的外键字段,不能与真的外键字段重名
@property
def publish_info(self):  # 单个数据

    return {
        'name': self.publish.name,
        'address': self.publish.address,
    }

# 自定义反序列化的外键字段,不能与真的外键字段重名
@property
def author_list(self):
    author_list_temp = []  # 存放所有作者格式化成数据的列表
    authors = self.authors.all()  # 所有作者
    for author in authors:  # 遍历处理所有作者
        author_dic = {
            'name': author.name,
        }
        try:  # 有详情才处理详情信息
            author_dic['mobile'] = author.detail.mobile
        except:
            author_dic['mobile'] = '无'

        author_list_temp.append(author_dic)  # 将处理过的数据添加到数据列表中

    return author_list_temp  # 返回处理后的结果

def __str__(self):
    return self.name

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

class Author(BaseModel):
name = models.CharField(max_length=64)

class AuthorDetail(BaseModel):
mobile = models.CharField(max_length=64)
author = models.OneToOneField(to=Author, related_name=‘detail‘, db_constraint=False, on_delete=models.CASCADE)

原文地址:https://www.cnblogs.com/zhm-cyt/p/12117915.html

时间: 2024-08-30 04:11:04

bookserlizer 十大接口的相关文章

导包补充,深度查询(深度序列化),十大接口

目录 一.导包补充 二.深度查询 1. 子序列化和depth方法 (1)什么是子序列化 (2)__all__ 方法 exclude方法 (3)子序列化实例 2. 插拔式 三.十大接口 1. 十大接口中注意点(很重要) 2. 实例 一.导包补充 在导包时,如果用from 文件1 import *,则文件1中的以下划线开头的变量,都不能访问.无论是单下划线还是双下线. 用import 文件1的方式,还是能访问到文件1中以下划线开头的变量,没有影响. 当我们用from 文件1 import *的方式导

序列化类外键字段的覆盖,十大接口序列化总结,视图家族

序列化类外键字段的覆盖 """ 1)在序列化类中自定义字段,名字与model类中属性名一致,就称之为覆盖操作 (覆盖的是属性的所有规则:extra_kwargs中指定的简易规则.model字段提供的默认规则.数据库唯一约束等哪些规则) 2)外键覆盖字段用PrimaryKeyRelatedField来实现,可以做到只读.只写.可读可写三种形式 只读:read_only=True 只写:queryset=关联表的queryset, write_only=True 可读可写:que

drf序列化高级、自定义只读只写、序列化覆盖字段、二次封装Response、数据库查询优化(断关联)、十大接口、视图家族、自动补全图片链接

目录 自定义只读 自定义只写 序列化覆盖字段 二次封装Response 数据库关系分析 断外键关联关系 ORM操作外键关系 ORM四种关联关系 基表 序列化类其他配置(了解) 十大接口 BaseSerializer初始化方法 十大接口序列化总结 单查群查 单增群增 单删群删 单整体改/群整体改 单局部改/群局部改 群增群改配置 十大接口小结 字段提供就校验,不提供拉到 DjangoORM内置优化机制:一次最多查21条数据 models.py response.py serializers.py

CSIC_716_20200221【drf--自定义外键字段、十大接口】

自定义序列化外键字段: 在序列化组件中  serializers.PrimaryKeyRelatedField(read_only=True)  #只读覆盖 serializers.PrimaryKeyRelatedField(queryset=.....all()  )  # 可读可写 serializers.PrimaryKeyRelatedField(queryset=.....all() ,write_only=True  )  # 只写 原文地址:https://www.cnblogs

学习游戏要学习编程语言吗?十大主流编程语言解析

计算机的发展,促使了一个新的职业的出现,程序员是近些年出现的并且得到了广泛关注的一个职业,相信这也是很多莘莘学子的职业梦想.但程序员也有很多种,并不是每一个程序员能够精通所有的编程语言.所谓术业有专攻,如果将来志在编程世界的网友就要注意了,今天给大家推荐一下2014年最流行的编程语言,他们可以说是未来程序员们生存的工具. 1.JavaScript JavaScript在Web应用上有着非常大的需求,JavaScript主要用于实现为Web浏览器,以提供增强的用户界面和动态网站. 直到google

对比深度学习十大框架:TensorFlow 并非最好?

http://www.oschina.net/news/80593/deep-learning-frameworks-a-review-before-finishing-2016 TensorFlow 链接:https://www.tensorflow.org/ 对于那些听说过深度学习但还没有太过专门深入的人来说,TensorFlow 是他们最喜欢的深度学习框架,但在这里我要澄清一些事实. 在 TensorFlow 的官网上,它被定义为「一个用于机器智能的开源软件库」,但我觉得应该这么定义:Te

十大免费移动程序测试框架(Android/iOS)

十大免费移动程序测试框架(Android/iOS) 概述:本文将介绍10款免费移动程序测试框架,帮助开发人员简化测试流程,一起来看看吧. Bug是移动开发者最头痛的一大问题.不同于Web应用程序开发,你可以时刻发现并修复Bug,而移动应用程序中的Bug隐藏得很深,直到用户使用时才发现问题.这样一来,不仅有损产品在市场上的名声,而且还会影响销售.所以在产品发布以前,开发人员需要严格测试程序.本文将介绍10款免费移动程序测试框架,帮助开发人员简化测试流程,一起来看看吧. Appium for iOS

罗森伯格再次荣获中国十大布线品牌以及数据中心产品应用奖

由中国工程建设标准化协会主办,中国数据中心工作组(CDCC).综合布线工作组联合承办的2016中国数据中心年度论坛于11月15~16日在北京新云南假日大酒店召开.论坛中揭晓了2016年度中国综合布线十大品牌.罗森伯格作为全球可信赖的通讯网络供应商, 在本次大会上再次荣获"中国十大布线品牌"以及"数据中心产品应用奖"两大奖项."中国综合布线十大品牌"评选活动是综合布线工作组基于对综合布线产业的长期关注和理解,以及对于品牌竞争力的透彻分析,权威开展的

十大技巧快速提升Android应用开发性能

一个应用程序要想开发成功,质量至关重要.用户要求它们决定安装到自己设备上的Android应用程序反应迅即.性能合理.如果应用程序未能提供好用的功能和稳定的用户体验,那么很快就会被卸载掉.本文我们将介绍十大技巧快速提升Android应用开发性能. 1:首先要有良好的编程习惯 要成为一名优秀的资源管理员;既要运用常识,还要使用公认的算法和标准的设计模式.在资源使用方面,如果你打开了资源,要记得关闭资源.要尽量晚地获取,尽量早地释放.这些由来已久的编程准则同样适用于你的Android应用程序,如果它们