首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django-taggit prefetch_related

Django-taggit prefetch_related
EN

Stack Overflow用户
提问于 2012-10-17 10:00:34
回答 4查看 2K关注 0票数 7

我现在正在构建一个基本的时间日志应用程序,我有一个使用django-taggit的todo模型。我的Todo模型如下所示:

代码语言:javascript
复制
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,我必须查询数据库来获取标签。我的理解是:

代码语言:javascript
复制
unique_tags = { tag.name.lower() for todo in project.todo_set.all() for tag in todo.tags.all() }

这工作得很好,但是对于项目中的每个todo,它都会运行一个单独的查询来获取所有的标签。我想知道是否有任何方法可以做类似于prefetch_related的事情,以避免这些重复的查询:

代码语言:javascript
复制
unique_tags = { tag.name.lower() for todo in project.todo_set.all().prefetch_related('tags') for tag in todo.tags.all() }

运行前面的代码会给出错误:

代码语言:javascript
复制
'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,但是它看起来并没有得到明确的答案。我希望有人能帮我个忙。谢谢!

EN

回答 4

Stack Overflow用户

发布于 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。

票数 7
EN

Stack Overflow用户

发布于 2013-03-27 18:21:16

略显老土的语气:

代码语言:javascript
复制
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使用的内部类。

票数 3
EN

Stack Overflow用户

发布于 2013-08-27 16:31:53

使用django-tagging和usage_for_model方法

代码语言:javascript
复制
 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.
    """
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12926036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档