Django: How to prefetch related for a model instance. Perhaps by wrapping in a queryset?

僤鯓⒐⒋嵵緔 提交于 2020-08-08 06:36:45

问题


I use Django rest framework and I have decent nesting in my model relations.

I'm working on optimizing my queries. Many of my functions consume or manipulate a single instance of model and it's often further downstream in the data flow that it turns out I need some prefetching. One classic instance of this is with DRF serializers. Here's an example.

@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

I've seen some solutions suggesting passing queryset with prefetch_related in the context although I haven't been able to get a full picture on how that would work (I've only found a couple of places that discuss it partially, might open a whole other question on that).

An easy fix (and one that would generalize beyond serializers) would be if I can have a wrapper function to wrap my instance in a queryset and then call prefetch on that, passing it into the serializer.

Something like:

def queryset_wrap(instance):
    return type(instance).objects.filter(id=instance.id)

I'm wondering if there's a better way to do this.


回答1:


I haven't yet used this myself, but I believe that it is the prefetch_related_objects() function that you are looking for, introduced in Django 1.10

From the docs:

Prefetches the given lookups on an iterable of model instances. This is useful in code that receives a list of model instances as opposed to a QuerySet; for example, when fetching models from a cache or instantiating them manually.

Pass an iterable of model instances (must all be of the same class) and the lookups or Prefetch objects you want to prefetch for. For example:

>>> from django.db.models import prefetch_related_objects
>>> restaurants = fetch_top_restaurants_from_cache()  # A list of Restaurants
>>> prefetch_related_objects(restaurants, 'pizzas__toppings')

Since it takes an iterable, you can wrap your instance in a list:

prefetch_related_objects([profile], "relevant_attribute_1", "relevant_attribute_2")


来源:https://stackoverflow.com/questions/54759975/django-how-to-prefetch-related-for-a-model-instance-perhaps-by-wrapping-in-a-q

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!