优化django查询来拉外键和django-taggit关系 [英] Optimize django query to pull foreign key and django-taggit relationship

查看:177
本文介绍了优化django查询来拉外键和django-taggit关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个定义如下的todo模型:

I have a todo model defined below:

class Action(models.Model):
    name = models.CharField("Action Name", max_length=200, unique = True)

    complete = models.BooleanField(default=False, verbose_name="Complete?")

    reoccurance = models.ForeignKey(Reoccurance, blank=True, null=True, verbose_name="Reoccurance")
    notes = models.TextField("Notes", blank=True)

    tags = TaggableManager()

class Reoccurance(models.Model):
    label = models.CharField("Label", max_length=50, unique = True)
    days = models.IntegerField("Days")

我想列出所有不完整的操作:

I want to list all of the actions that are incomplete:

actions = Action.objects.filter(complete=False)

我的动作列表的模板循环:

My template loops of the actions list:

{% for action in actions %}
    <p>{{ action }}</p>
    {% if action.reoccurance %}
        <p>{{ action.reoccurance }}</p>
    {% endif %}
    {% for tag in action.tags.all %}
        <span>{{ tag }}</span>{% if not forloop.last %}, {% endif %}
    {% endfor %}
{% endfor %}

使用 django-debug-toolbar ,我看到对于每个动作,我在{%if(action.reoccurance%)和{%for action.tags.all%}中的数据库中击中数据库。

Using django-debug-toolbar, I see that for every action, I'm hitting the database on {% if action.reoccurance %} and {% for tag in action.tags.all %}.

是否有写一个更好的方式来编写我的查询,以便数据库不循环循环的每次迭代?我认为这与select_related有关,但我不知道如何处理 django-taggit

Is there a better way to write my query so that the database isn't pinged for every iteration of the loop? I think it has something to do with select_related, but I'm not sure what to do about django-taggit.

更新我有一部分答案。 select_related可以正常工作,但是我不得不指定重现,可能是因为我无法使用它来代替标签:

Update I got part of my answer. select_related does work, but I had to specify reoccurance, probably because I can't use it for tags:

actions = Action.objects.select_related('reoccurance').filter(complete=False)

问题依然是我在模板循环中为每个action.tags.all命中数据库。是否可以在django-taggit上使用某种预取?

The problem still remains that I hit the database for every "action.tags.all" in the template loop. Is it possible to use some sort of prefetch on django-taggit?

推荐答案

可以使用 prefetch_related 检索标签,但您需要围绕tags属性进行回绕,因为 - 正如jdi所说 - 这是一个自定义管理器,而不是一个真正的关系。相反,您可以执行以下操作:

It's possible to use prefetch_related to retrieve the tags, but you need to sidestep around the 'tags' property, since - as jdi says - this is a custom manager rather than a true relation. Instead, you can do:

actions = Action.objects.select_related('reoccurance')。filter(complete = False)\
.prefetch_related('tagged_items__tag')

不幸的是, action.tags.all 在你的模板代码中将不会使用预取,并且最终会自己做查询 - 所以你需要采取相当麻木的步骤绕过标签的经理:

Unfortunately, action.tags.all in your template code will not make use of the prefetch, and will end up doing its own query - so you need to take the rather hacky step of bypassing the 'tags' manager there too:

{% for tagged_item in action.tagged_items.all %}
    <span>{{ tagged_item.tag }}</span>{% if not forloop.last %}, {% endif %}
{% endfor %}

(Ed .:如果你收到'QuerySet'对象没有属性'prefetch_related'',那就表明你在一个Django版本低于1.4,其中prefetch_related不可用。)

(Ed.: if you're getting "'QuerySet' object has no attribute 'prefetch_related'", that suggests that you're on a version of Django below 1.4, where prefetch_related isn't available.)

这篇关于优化django查询来拉外键和django-taggit关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆