Context: Foo
is a class that has a foreignKey field pointing to a Bar
object. Several Foo
s may refer to the same Bar
. (Many to one)
I need to reference several fields of a Foo
object's foreignkey (Bar.field
and Bar.field2
), but it seems that each time I do so it runs a separate query.
As a result, referencing these fields can take forever.
Is there a way to get all the Bar
objects in a single query? Or is there a better way to speed it up?
foo_list = Foo.objects.filter(params) # takes 0.001 开发者_如何学JAVAsec, returns 10k objects
result = []
for f in foo_list:
# this part takes 40 seconds due to the huge number of queries
bar = f.bar # Foo contains a foreignKey reference to the Bar class
result.append({
"field": f.field,
"barField": bar.barField,
"barField2": bar.barField2,
# this way was even worse
# "barField": f.bar.barField,
# "barField2": f.bar.barField2,
})
foo_list = Foo.objects.filter(params).select_related()
does the job. The rest of the code would remain the same, but
for f in foo_list:
f.bar
would use the cached objects
Yes, you can use the select_related
method on your queryset (https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.select_related), which will do the joins for you in the initial query. So in your case, something like:
foo_list = Foo.objects.filter(params).select_related()
If you have a very deep chain of linked models, it may be worth also limiting the depth so that you only get the bar objects (and not any additional links beyond that like .select_related(depth=1)
Use relationship look up's eg:
foo_list = Foo.objects.filter(params).values('field','bar__barField','bar__barField2')
This will do the job in one query and the result set will have the required fields as well.
精彩评论