Question

I using Django tagging project.

That is was very stable project. Working on django 1.3.

But i have a problem.

# in models.py
from tagging.fields import TagField
class Blog(models.Model):
     title = models.CharField(max_length = 300)
     content = models.TextField()
     tags = TagField()
     author = models.ForeignKey(User)

# in views.py
def blog_list(request):
    # I Want to use select related with tags
    blogs = Blog.objects.all().select_related("user", "tags") # ????
    ....

# in Templates
{% load tagging_tags %}
{% for blog in blogs %}
    {% tags_for_object blog as tags %}
    {{blog.title}}
    {% for tag in tags %}
        <a href="{% url tag_detail tag_id=tag.pk %}">{{tag}}</a>
    {% endfor %}
{% endfor %}
Was it helpful?

Solution

django-tagging uses a generic foreign key to your model, so you can't just use select_related.

Something like this should do the trick though:

from django.contrib.contenttypes.models import ContentType
from collections import defaultdict
from tagging.models import TaggedItem

def populate_tags_for_queryset(queryset):
    ctype = ContentType.objects.get_for_model(queryset.model)
    tagitems = TaggedItem.objects.filter(
        content_type=ctype,
        object_id__in=queryset.values_list('pk', flat=True),
    )
    tagitems = tagitems.select_related('tag')
    tags_map = defaultdict(list)
    for tagitem in tagitems:
        tags_map[tagitem.object_id].append(tagitem.tag)
    for obj in queryset:
        obj.cached_tags = tags_map[obj.pk]

OTHER TIPS

I have recently encountered the same problem and solved it without a single db query. Indeed, we don't need tag id to get url. As tag name is unique and is db_index you can get url using name field instead of id. E.g.

# your_app/urls.py

url(r'tag/(?P<tag_name>[-\w]+)$', tag_detail_view, name='tag_detail')

Also, tagging TagField gives us a string with tag names, like 'python,django'. So we can write a custom template filter:

# your_app/templatetags/custom_tags.py

from django.urls import reverse

@register.filter
def make_tag_links(tags_str):
    return ', '.join([u'<a href="%s">%s</a>' % (reverse(
        'tag_detail', args=[x]), x) for x in tags_str.split(',')])

And then you can write in template:

# your_list_template.html

{% for blog in blogs %}
    {{blog.title}}
    {% if blog.tags %}
        {{ blog.tags|make_tag_links|safe }}
    {% endif %}
{% endfor %}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top