我现在正在构建一个基本的时间日志应用程序,我有一个使用django-taggit的todo模型。我的Todo模型如下所示:
class Todo(models.Model):
project = models.ForeignKey(Project)
description = models.CharField(max_length=300)
is_done = models.BooleanField(default=False)
billable = models.BooleanField(default=True)
date_completed = models.DateTimeField(blank=True, null=True)
completed_by = models.ForeignKey(User, blank=True, null=True)
tags = TaggableManager()
def __unicode__(self):
return self.description我正在尝试为项目中的所有Todo获取唯一标签列表,我已经设法使用一组理解来使其工作,但是对于项目中的每个Todo,我必须查询数据库来获取标签。我的理解是:
unique_tags = { tag.name.lower() for todo in project.todo_set.all() for tag in todo.tags.all() }这工作得很好,但是对于项目中的每个todo,它都会运行一个单独的查询来获取所有的标签。我想知道是否有任何方法可以做类似于prefetch_related的事情,以避免这些重复的查询:
unique_tags = { tag.name.lower() for todo in project.todo_set.all().prefetch_related('tags') for tag in todo.tags.all() }运行前面的代码会给出错误:
'tags' does not resolve to a item that supports prefetching - this is an invalid parameter to prefetch_related().我确实看到有人在这里问了一个非常类似的问题:Optimize django query to pull foreign key and django-taggit relationship,但是它看起来并没有得到明确的答案。我希望有人能帮我个忙。谢谢!
发布于 2014-02-10 14:56:28
Taggit现在直接在标记字段上支持prefetch_related (在版本0.11.0和更高版本中,发布2013-11-25)。
此功能是在this pull request中引入的。在the test case for it中,请注意,使用.prefetch_related('tags')预取标签后,列出标签的额外查询次数为0。
发布于 2013-03-27 18:21:16
略显老土的语气:
ct = ContentType.objects.get_for_model(Todo)
todo_pks = [each.pk for each in project.todo_set.all()]
tagged_items = TaggedItem.objects.filter(content_type=ct, object_id__in=todo_pks) #only one db query
unique_tags = set([each.tag for each in tagged_items])解释
我说它是黑客,因为我们必须使用taggit内部使用的TaggedItem和ContentType。
Taggit不会为您的特定用例提供任何方法。原因是因为它是通用的。taggit的目的是任何模型的任何实例都可以被标记。因此,它使用了ContentType和GenericForeignKey。
taggit内部使用的模型是Tag和TaggedItem。Model标记仅包含标记的字符串表示形式。TaggedItem是用于将这些标签与任何对象相关联的模型。由于标记应该可以与任何对象关联,因此TaggedItem使用模型ContentType。
taggit提供的apis,如tags.all(),tags.add()等,在内部使用了这个模型上的TaggedItem和过滤器来为你提供特定实例的标签。
因为,您的需求是获取特定对象列表的所有标记,因此我们必须使用由taggit使用的内部类。
发布于 2013-08-27 16:31:53
使用django-tagging和usage_for_model方法
def usage_for_model(self, model, counts=False, min_count=None, filters=None):
"""
Obtain a list of tags associated with instances of the given
Model class.
If ``counts`` is True, a ``count`` attribute will be added to
each tag, indicating how many times it has been used against
the Model class in question.
If ``min_count`` is given, only tags which have a ``count``
greater than or equal to ``min_count`` will be returned.
Passing a value for ``min_count`` implies ``counts=True``.
To limit the tags (and counts, if specified) returned to those
used by a subset of the Model's instances, pass a dictionary
of field lookups to be applied to the given Model as the
``filters`` argument.
"""https://stackoverflow.com/questions/12926036
复制相似问题