Jad*_*d S 5 python django query-optimization django-rest-framework
我使用 Django Rest 框架,并且我的模型关系中有不错的嵌套。
我正在努力优化我的查询。我的许多函数都会消耗或操作模型的单个实例,并且通常在数据流的更下游,事实证明我需要一些预取。一个典型的例子是 DRF 序列化器。这是一个例子。
@api_view(['GET'])
def fetch_user_profile(request):
profile = request.user.profile # has many nested relationships
return Response(UserProfileSerializer(profile).data, status=status.HTTP_200_OK) # this ends up taking many queries
Run Code Online (Sandbox Code Playgroud)
我已经看到一些解决方案建议在上下文中传递查询集,prefetch_related
尽管我无法全面了解它是如何工作的(我只找到了几个部分讨论它的地方,可能会打开一个完整的其他地方的问题)。
一个简单的修复(并且可以推广到序列化器之外的修复)是,如果我可以有一个包装函数将我的实例包装在查询集中,然后对其调用预取,将其传递到序列化器中。
就像是:
def queryset_wrap(instance):
return type(instance).objects.filter(id=instance.id)
Run Code Online (Sandbox Code Playgroud)
我想知道是否有更好的方法来做到这一点。
小智 5
我自己还没有使用过这个,但我相信它是prefetch_related_objects()
您正在寻找的功能,在 Django 1.10 中引入
来自文档:
在可迭代的模型实例上预取给定的查找。这在接收模型实例列表而不是查询集的代码中非常有用;例如,从缓存中获取模型或手动实例化它们时。
传递模型实例的可迭代对象(必须全部属于同一类)以及要预取的查找或预取对象。例如:
>>> from django.db.models import prefetch_related_objects
>>> restaurants = fetch_top_restaurants_from_cache() # A list of Restaurants
>>> prefetch_related_objects(restaurants, 'pizzas__toppings')
Run Code Online (Sandbox Code Playgroud)
由于它需要一个可迭代对象,因此您可以将实例包装在列表中:
prefetch_related_objects([profile], "relevant_attribute_1", "relevant_attribute_2")
Run Code Online (Sandbox Code Playgroud)