django-taggit: Is there a way to produce less db queries?
Asked Answered
P

2

6

Say I have a model:

class Entry(models.Model):
    ...
    tags = TaggableManager()

When I iterate over Entry.objects.all() in a template, entry.tags.all produces one more query to the database. Is it possible to reduce queries number? Using something like select_related() (I know it won't work, since django-taggit uses manytomany relation, but I am sure there should be a way to select all entries with related tags in 1 hit)?

Plane answered 1/7, 2011 at 11:19 Comment(1)
possible duplicate of Django-taggit prefetch_related, or maybe #12205011Estonian
N
3

From Django 1.4 onward, you can use prefetch_related to retrieve one-to-many relations on a queryset in a single query. Unfortunately this doesn't work brilliantly with django-taggit, because the 'tags' property is a manager rather than a true relation, and so prefetch_related can't make sense of it. Instead, you need to follow the tagged_items relation:

entries = Entry.objects.prefetch_related('tagged_items__tag')

You then need to go through some similar contortions in the template code to access the prefetched tags, because entry.tags.all will run another query rather than making use of the prefetch:

{% for tagged_item in entry.tagged_items %}
    <li>{{ tagged_item.tag.name }}</li>
{% endfor %}
Nitrite answered 3/10, 2013 at 17:50 Comment(2)
Just a note - this caused a GenericRelatedObjectManager error for me. I changed entry.tagged_items to entry.tagged_items.all and it worked, but not with any improvement in SQL queries over the original code. Confused here.Snub
django-taggit now supports prefetch_related('tags') since v0.11 - https://mcmap.net/q/1155494/-django-taggit-prefetch_relatedDogeatdog
A
0

Try using Select Reverse it's designed to grab the entirity of a many2many relationship with a single query.

Adolfo answered 1/7, 2011 at 13:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.