使用 select_related()、prefetch_related()、defer() 和 only() 自动优化序列化器
项目描述
汽车相关
AutoRelated 包自动为 django-rest 序列化程序创建正确的 djangoselect_related()和prefetch_related()方法。only()
- 将您的序列化程序传递给 Tracer 对象
- 使用返回的参数构建您的查询
- 您的查询已优化
要求
AutoRelated 是针对其开发和测试的;
- Django 版本:3.0、3.0.5
- Django REST 框架版本:3.10.3、3.11.0
- Python 版本:3.6、3.7、3.8
它只需要:
- 姜戈
- Django REST 框架
除上述以外的开发:
- Django 调试工具栏
安装
要安装它,请使用
$ pip install auto-related
用法
如果您在 serializers.py 文件中定义了这样的序列化程序;
from restframework import serializers
class SomeSerializer(serializer.ModelSerializer):
field=SomeotherSerializer(many=True)
.
.
.
你可以像这样在你的视图中使用它;
from auto_related.tracer import Trace, optimized_queryset_given_trails
from rest_framework import status,generics
class ParentList(generics.ListAPIView):
serializer_class = SomeSerializer
def get_queryset(self):
t=Tracer(SomeSerializer)
traces=t.trace()
s,p=optimized_queryset_given_trails(traces)
return SomeSerializer.model.objects.select_related(*s)\
.prefetch_related(*p)\
.only(*t.build_only())
或者你可以使用基本上做同样事情的mixin
from auto_related.mixin import ViewMixin, ViewMixinWithOnlyOptim
from rest_framework import status,generics
#this mixin does not use only() and defer() optimization
class ParentList(ViewMixin, generics.ListAPIView):
serializer_class = SomeSerializer
# you can pass extra parameters here for SerializerMethodField if you do not use auto-related's MethodField
queryset=Parent.objects.all()
#this mixin uses only() and defer() optimization
class ParentList(ViewMixinWithOnlyOptim, generics.ListAPIView):
serializer_class = SomeSerializer
queryset=Parent.objects.all()
如果你有一个 SerializerMethodField:
如果您的序列化程序中有一个 SerializerMethodField 需要评估一个查询集,那么它无法通过自动相关自动检测到,因为检查一个函数真的很困难。作为一种解决方案,您可以使用来自 auto-related.method_field 的 MethodField,它与 SerializerMethodField 几乎相同,只是它有一个 sources 属性,稍后可用于 auto-related 确定正确使用 select_related()、prefetch_related() 并且仅()。
from auto_related.method_field import MethodField
class SomeSerializerWithMethodField(serializer.ModelSerializer):
field1=MethodField(many=True, sources=['related_object_set'])
field2=MethodField(many=True, sources=['child__related_object_set', 'related_object_set'])
get_field1(self, obj):
# here related_object is accessed hence it sould be added to sources
return obj.related_object_set.all().count()
get_field2(self, obj):
# here related_object and child.related_object is accessed hence they sould be added to sources
return obj.child.related_object_set.all().count() + obj.related_object_set.all().count()
class Meta:
model=modelA
class AnotherSerializer(serializer.ModelSerializer):
# You can use above serializer which includes a SerializerMethodField in another serializer safely.
# This way you do not need to deal with nested usage of SerilizerMethodField.
# They are automatically prepended with necessary model and field names when used in another serializer.
# Also sources are automatically splitted into select_related and prefetch_related in a way
# which minimizes database hits.
field=SomeSerializerWithMethodField(many=True, source='modelA')
class Meta:
model=modelB
MethodField 的实现与 rest-framework 中的 SerializerMethodField 几乎相同。事实上,如果你不向它传递 sources 参数,它是一样的。auto_related.method_field import MethodField as SerializerMethodField因此,您可以在不更改代码的情况下导入 like ,并且您只需为必要的字段设置源参数。
这个怎么运作
首先,一个 util 函数get_all_sources()通过遍历它的所有字段(包括嵌套的序列化器的字段)来深入检查一个序列化器。假设您有这样的序列化程序;
class SomeSerializer(serializer.ModelSerializer):
field=SomeOtherSerializer(many=True, source='some_other')
text=CharField()
class SomeOtherSerializer(serializer.ModelSerializer):
name=CharField()
attr=IntegerField()
然后通过以下方式获得序列化器的所有源;
get_all_sources(SomeSerializer)
#returns ['field', 'text',' some_other.name', 'some_other.attr']
这是该序列化程序在与数据一起传递时将访问的所有属性。我们必须以某种方式检查这些来源以决定要预取什么。
然后,跟踪器对象在此序列化程序分配到的模型上跟踪所有这些源。例如 some_other.attr 源首先访问 some_other 关系字段,然后访问 SomeOther 模型的 attr integerfield。请注意,这些字段与其余框架字段无关,它们是 django 的字段对象。字段帮助我们决定预取什么。例如,如果一个字段是相关或反向相关的字段,那么可以说它应该被预取。然而,在 django 中有两种方法可以做到这一点,它们是select_related和prefetch_related. 字段类有助于确定哪个是哪个。例如,可以使用 onetoone 字段预取,select_related但我们应该使用prefetch_relatedmanytomany 字段或反向相关字段等。
发展
想贡献?伟大的!
目前没有自动化测试。您可以克隆 repo 并运行测试项目;
$ cd projectfolder/autorelated/tests
$ python manage.py runserver
项目中安装了 Django 工具栏,以便您可以检查执行了多少查询以及许多其他事情以用于测试目的。例如,您可以去比较 auto_related 应用http://localhost:8080/test/course和http://localhost:8080/test/course/slow未应用查询之间的速度和查询计数差异。测试项目中的每个 url 都有其对应部分...url/slow,它不使用 auto_related 并且仅用model.objects.all()作查询集。
待办事项
- 写作测试
- 检查传递给序列化程序的查询集或模型实例,以检查它们是否被缓存和正确配置,如果没有自动优化它们。
- 在不需要 django 模型实例时使用
values()而不是使用。only() - 为了能够将整个包用作调试工具,当 DEBUG=True 时,它可以警告缺少优化
执照
麻省理工学院
项目详情
下载文件
下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。
源分布
内置分布
auto_related -0.0.4.tar.gz 的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | 6837c9d28a4144f873200523bfe39ba32757bc9fcc8fcd4f42e04fdcd8afb0a4 |
|
| MD5 | f420b91ded3a663e48b8a41e2e4dac62 |
|
| 布莱克2-256 | 980202e2de5f1724875dff5ac1165ac8339fb5b61b10d444348fd81c9b29a114 |
auto_related -0.0.4-py3-none-any.whl 的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | f56faa405d5924875060ff080b752c21e9c962ffe9150ed3fb4ccfdcc505cad6 |
|
| MD5 | 5fbbbc9fddd03d2ea1567dec2ba87360 |
|
| 布莱克2-256 | a200eed9631f49530d76a7fdc170b657c98ccb7fe9076ef11df11955f5fdc3bf |