drf序列化器使用时性能优化之根据请求类型动态变更serializer及个性化序列化字段及 Django REST-FlexFields使用

根据请求类型动态变更serializer

我们在drf开发中我们遇到增删改查数据时,会遇到一些针对于增删改查的不同请求的json请求, 我们可以使用不同的序列化器满足需求,闲话少说,直接上代码吧

  • 首先我们定义相关的models.py中添加相关的模型
  1. from django.db import models
  2. class BookModels(models.Model):
  3. id = models.BigAutoField("图书记录id号", primary_key=True)
  4. Isbn_Card = models.CharField("图书isbn码", max_length=30, null=False, )
  5. Book_Name = models.CharField("图书名称", max_length=100, null=False, blank=False)
  6. Book_author = models.CharField("图书作者", max_length=100, null=False, blank=False)
  7. Book_press = models.CharField("图书出版社", max_length=100, null=False, blank=False)
  8. Book_stock = models.IntegerField("图书库存", default=0, null=False, blank=False)
  9. Book_Creation_time = models.DateField("图书入库时间", auto_now_add=True, null=False, blank=False)
  10. Book_notes = models.TextField("简介备用", null=False, blank=False)
  11. Price = models.DecimalField("图书单价", max_digits=10000, decimal_places=2, null=False, blank=False, default=0)
  12. class Meta:
  13. verbose_name = "图书信息管理"
  14. db_table = "BookInfo_Table"
  15. verbose_name_plural = verbose_name
  16. def __str__(self):
  17. return f"{self.id}:{self.Isbn_Card}: {self.Book_Name}: {self.Book_author}:{self.Book_press}"
  18. class BookAnother(models.Model):
  19. name = models.CharField("name", max_length=12)
  20. BookModel = models.ForeignKey(BookModels, on_delete=models.DO_NOTHING, verbose_name="图书信息管理", null=True)
  21. class Meta:
  22. verbose_name = "BookAnother"
  23. db_table = "BookAnother_Table"
  24. verbose_name_plural = verbose_name
  • 其次在Serializer.py中新建相关的序列化器
  1. # -*- coding: utf-8 -*-
  2. # @Time : 2021/2/9 下午3:09
  3. # @Author : void bug
  4. # @FileName: Serializer.py
  5. # @Software: PyCharm
  6. from rest_framework import serializers
  7. from apps.Book.models import *
  8. class BookSerializers(serializers.ModelSerializer):
  9. class Meta:
  10. model = BookModels
  11. fields = '__all__'
  12. class BookAnotherUpDateSerializer(serializers.ModelSerializer):
  13. class Meta:
  14. model = BookAnother
  15. fields = ("name",)
  16. class BookAnotherSerializer(serializers.ModelSerializer):
  17. class Meta:
  18. model = BookAnother
  19. fields = '__all__'
  • 最后我们编写相关的ViewSet.py文件
  1. # -*- coding: utf-8 -*-
  2. # @Time : 2021/2/9 下午3:12
  3. # @Author : void bug
  4. # @FileName: ViewSet.py
  5. # @Software: PyCharm
  6. from rest_framework import viewsets
  7. from apps.Book.Serializer import *
  8. class BookViewSet(viewsets.ModelViewSet):
  9. serializer_class = BookSerializers
  10. queryset = BookModels.objects.all()
  11. class BookAnotherViewSet(viewsets.ModelViewSet):
  12. serializer_class = BookAnotherSerializer
  13. queryset = BookAnother.objects.all()
  14. def get_serializer_class(self):
  15. # 根据请求类型动态变更serializer
  16. if self.action == "update":
  17. return BookAnotherUpDateSerializer
  18. return BookAnotherSerializer
  • 我们看下效果

58F4B223-1A5B-45be-953B-576700415EA7.pngC3FDC8E8-A21B-486e-947B-5D8174B190DC.png

个性化序列化字段

先在我们实现了根据请求类型动态变更serializer,但是现在进行一些优化,但是我们为什么要进行优化呢,现在我们修改成功后只显示了 name 字段,但是我们修改成功后应该时都显示出来,故现在我们只需要修改BookAnotherViewSet.py即可

  1. class BookAnotherUpDateSerializer(serializers.ModelSerializer):
  2. name = serializers.CharField(max_length=12, read_only=True)
  3. class Meta:
  4. model = BookAnother
  5. fields = '__all__'
  • 我们看下效果

0B628299-FBEA-4aa4-8A9B-9BAA7BAE335F.png88E0A912-0241-4e18-B826-D7F9FADA073A.png

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'])

安装

  1. pip install drf-flex-fields

配置序列化器

然后让您的序列化器子类FlexFieldsModelSerializer

  1. # -*- coding: utf-8 -*-
  2. # @Time : 2021/2/9 下午3:09
  3. # @Author : void bug
  4. # @FileName: Serializer.py
  5. # @Software: PyCharm
  6. from rest_flex_fields import FlexFieldsModelSerializer
  7. from rest_framework import serializers
  8. from apps.Book.models import *
  9. class BookSerializers(serializers.ModelSerializer):
  10. class Meta:
  11. model = BookModels
  12. fields = '__all__'
  13. class BookAnotherUpDateSerializer(FlexFieldsModelSerializer):
  14. name = serializers.CharField(max_length=12, read_only=True)
  15. class Meta:
  16. model = BookAnother
  17. fields = '__all__'
  18. expandable_fields = {
  19. "BookModel": BookSerializers
  20. }
  21. class BookAnotherSerializer(FlexFieldsModelSerializer):
  22. class Meta:
  23. model = BookAnother
  24. fields = '__all__'
  25. expandable_fields = {
  26. "BookModel": BookSerializers
  27. }

其他的不用修改

运行结果

http://127.0.0.1:8000/api/BookAnother/1/
D09B6779-65A6-46ae-8E33-64DD9FFB282A.png
http://127.0.0.1:8000/api/BookAnother/1/?expand=BookModel
7CF8E5A9-905E-493b-BDEB-266E545C0197.png

安全优化

我们现在修改一下

  1. # -*- coding: utf-8 -*-
  2. # @Time : 2021/2/9 下午3:09
  3. # @Author : void bug
  4. # @FileName: Serializer.py
  5. # @Software: PyCharm
  6. from rest_flex_fields import FlexFieldsModelSerializer
  7. from rest_framework import serializers
  8. from apps.Book.models import *
  9. class BookSerializers(serializers.ModelSerializer):
  10. class Meta:
  11. model = BookModels
  12. fields = '__all__'
  13. class BookReadOnlySerializer(serializers.ModelSerializer):
  14. Isbn_Card = serializers.CharField(read_only=True)
  15. Book_Name = serializers.CharField(read_only=True)
  16. Book_author = serializers.CharField(read_only=True)
  17. Book_press = serializers.CharField(read_only=True)
  18. Book_stock = serializers.IntegerField(read_only=True)
  19. Book_notes = serializers.CharField(read_only=True)
  20. Price = serializers.DecimalField(read_only=True, max_digits=10000, decimal_places=2)
  21. class Meta:
  22. model = BookModels
  23. fields = '__all__'
  24. class BookAnotherUpDateSerializer(FlexFieldsModelSerializer):
  25. name = serializers.CharField(max_length=12, read_only=True)
  26. class Meta:
  27. model = BookAnother
  28. fields = '__all__'
  29. expandable_fields = {
  30. "BookModel": BookReadOnlySerializer
  31. }
  32. class BookAnotherSerializer(FlexFieldsModelSerializer):
  33. class Meta:
  34. model = BookAnother
  35. fields = '__all__'
  36. expandable_fields = {
  37. "BookModel": BookSerializers
  38. }

运行结果
BBF4BD87-9886-4413-A729-909AC255AC93.png