Django标记select_related

时间:2012-03-28 05:07:40

标签: django django-queryset django-tagging django-select-related

我使用Django tagging项目。

那是非常稳定的项目。 致力于django 1.3。

但我有一个问题。

# 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 %}

2 个答案:

答案 0 :(得分:2)

django-tagging对您的模型使用通用外键,因此您不能只使用select_related

这样的事情应该可以解决这个问题:

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]

答案 1 :(得分:0)

我最近遇到了同样的问题并在没有单个数据库查询的情况下解决了它。实际上,我们不需要标记 id 来获取网址。由于标记名称是唯一的并且是db_index,因此您可以使用名称字段而不是 id 来获取网址。 E.g。

# your_app/urls.py

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

此外,标记TagField会为我们提供一个包含标记名称的字符串,例如&#39; python,django&#39; 。所以我们可以编写一个自定义模板过滤器:

# 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(',')])

然后你可以写模板:

# your_list_template.html

{% for blog in blogs %}
    {{blog.title}}
    {% if blog.tags %}
        {{ blog.tags|make_tag_links|safe }}
    {% endif %}
{% endfor %}