drf序列化器使用时性能优化之根据请求类型动态变更serializer及个性化序列化字段及 Django REST-FlexFields使用
根据请求类型动态变更serializer
我们在drf开发中我们遇到增删改查数据时,会遇到一些针对于增删改查的不同请求的json请求, 我们可以使用不同的序列化器满足需求,闲话少说,直接上代码吧
- 首先我们定义相关的
models.py中添加相关的模型
from django.db import modelsclass BookModels(models.Model):id = models.BigAutoField("图书记录id号", primary_key=True)Isbn_Card = models.CharField("图书isbn码", max_length=30, null=False, )Book_Name = models.CharField("图书名称", max_length=100, null=False, blank=False)Book_author = models.CharField("图书作者", max_length=100, null=False, blank=False)Book_press = models.CharField("图书出版社", max_length=100, null=False, blank=False)Book_stock = models.IntegerField("图书库存", default=0, null=False, blank=False)Book_Creation_time = models.DateField("图书入库时间", auto_now_add=True, null=False, blank=False)Book_notes = models.TextField("简介备用", null=False, blank=False)Price = models.DecimalField("图书单价", max_digits=10000, decimal_places=2, null=False, blank=False, default=0)class Meta:verbose_name = "图书信息管理"db_table = "BookInfo_Table"verbose_name_plural = verbose_namedef __str__(self):return f"{self.id}:{self.Isbn_Card}: {self.Book_Name}: {self.Book_author}:{self.Book_press}"class BookAnother(models.Model):name = models.CharField("name", max_length=12)BookModel = models.ForeignKey(BookModels, on_delete=models.DO_NOTHING, verbose_name="图书信息管理", null=True)class Meta:verbose_name = "BookAnother"db_table = "BookAnother_Table"verbose_name_plural = verbose_name
- 其次在
Serializer.py中新建相关的序列化器
# -*- coding: utf-8 -*-# @Time : 2021/2/9 下午3:09# @Author : void bug# @FileName: Serializer.py# @Software: PyCharmfrom rest_framework import serializersfrom apps.Book.models import *class BookSerializers(serializers.ModelSerializer):class Meta:model = BookModelsfields = '__all__'class BookAnotherUpDateSerializer(serializers.ModelSerializer):class Meta:model = BookAnotherfields = ("name",)class BookAnotherSerializer(serializers.ModelSerializer):class Meta:model = BookAnotherfields = '__all__'
- 最后我们编写相关的
ViewSet.py文件
# -*- coding: utf-8 -*-# @Time : 2021/2/9 下午3:12# @Author : void bug# @FileName: ViewSet.py# @Software: PyCharmfrom rest_framework import viewsetsfrom apps.Book.Serializer import *class BookViewSet(viewsets.ModelViewSet):serializer_class = BookSerializersqueryset = BookModels.objects.all()class BookAnotherViewSet(viewsets.ModelViewSet):serializer_class = BookAnotherSerializerqueryset = BookAnother.objects.all()def get_serializer_class(self):# 根据请求类型动态变更serializerif self.action == "update":return BookAnotherUpDateSerializerreturn BookAnotherSerializer
- 我们看下效果


个性化序列化字段
先在我们实现了根据请求类型动态变更serializer,但是现在进行一些优化,但是我们为什么要进行优化呢,现在我们修改成功后只显示了 name 字段,但是我们修改成功后应该时都显示出来,故现在我们只需要修改BookAnotherViewSet.py即可
class BookAnotherUpDateSerializer(serializers.ModelSerializer):name = serializers.CharField(max_length=12, read_only=True)class Meta:model = BookAnotherfields = '__all__'
- 我们看下效果


Django REST-FlexFields使用
好的我们已经实现了上述的功能了,但是我们现在项显示相关的外键的信息,现在我们需要导入一个外键的包Django REST-FlexFields
- Django REST Framework序列化程序的灵活,动态字段和嵌套模型。
- 总览
用于Django REST Framework的FlexFields(DRF-FF)是一个软件包,旨在为在DRF序列化程序中动态设置字段和嵌套模型提供功能的通用基准。该软件包的设计旨在简化,与DRF的基础类的纠缠最少。
主要优点:- 通过查询参数(
users/?expand=organization,friends)轻松设置可扩展为完全序列化的字段 - 通过以下任一方法选择字段的子集:
- 指定应包含哪些(
users/?fields=id,first_name) - 指定应排除的项目(
users/?omit=id,first_name)
- 指定应包含哪些(
- 使用点表示法可动态修改任意深度的字段(
users/?expand=organization.owner.roles) - 灵活的API-选项也可以直接传递给序列化器:
UserSerializer(obj, expand=['organization'])
- 通过查询参数(
安装
pip install drf-flex-fields
配置序列化器
然后让您的序列化器子类FlexFieldsModelSerializer:
# -*- coding: utf-8 -*-# @Time : 2021/2/9 下午3:09# @Author : void bug# @FileName: Serializer.py# @Software: PyCharmfrom rest_flex_fields import FlexFieldsModelSerializerfrom rest_framework import serializersfrom apps.Book.models import *class BookSerializers(serializers.ModelSerializer):class Meta:model = BookModelsfields = '__all__'class BookAnotherUpDateSerializer(FlexFieldsModelSerializer):name = serializers.CharField(max_length=12, read_only=True)class Meta:model = BookAnotherfields = '__all__'expandable_fields = {"BookModel": BookSerializers}class BookAnotherSerializer(FlexFieldsModelSerializer):class Meta:model = BookAnotherfields = '__all__'expandable_fields = {"BookModel": BookSerializers}
其他的不用修改
运行结果
http://127.0.0.1:8000/api/BookAnother/1/
http://127.0.0.1:8000/api/BookAnother/1/?expand=BookModel
安全优化
我们现在修改一下
# -*- coding: utf-8 -*-# @Time : 2021/2/9 下午3:09# @Author : void bug# @FileName: Serializer.py# @Software: PyCharmfrom rest_flex_fields import FlexFieldsModelSerializerfrom rest_framework import serializersfrom apps.Book.models import *class BookSerializers(serializers.ModelSerializer):class Meta:model = BookModelsfields = '__all__'class BookReadOnlySerializer(serializers.ModelSerializer):Isbn_Card = serializers.CharField(read_only=True)Book_Name = serializers.CharField(read_only=True)Book_author = serializers.CharField(read_only=True)Book_press = serializers.CharField(read_only=True)Book_stock = serializers.IntegerField(read_only=True)Book_notes = serializers.CharField(read_only=True)Price = serializers.DecimalField(read_only=True, max_digits=10000, decimal_places=2)class Meta:model = BookModelsfields = '__all__'class BookAnotherUpDateSerializer(FlexFieldsModelSerializer):name = serializers.CharField(max_length=12, read_only=True)class Meta:model = BookAnotherfields = '__all__'expandable_fields = {"BookModel": BookReadOnlySerializer}class BookAnotherSerializer(FlexFieldsModelSerializer):class Meta:model = BookAnotherfields = '__all__'expandable_fields = {"BookModel": BookSerializers}
运行结果
