2012-08-30 87 views
3

我在下面定義的待辦事項模式:優化Django的查詢拉外鍵和Django的taggit關係

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") 

我要列出所有不完整的行動:

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

我操作列表中的模板循環:

{% 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 in action.tags.all%}中。

有沒有更好的方式來編寫我的查詢,以便數據庫不會針對循環的每次迭代進行ping?我認爲它與select_related有關,但我不知道該怎麼做django-taggit

更新我得到了我的答案的一部分。 select_related的工作,但我必須指定reoccurance,可能是因爲我不能用它來標記:

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

的問題仍然是我打的數據庫,每一個「action.tags.all」模板循環。是否有可能在django-taggit上使用某種預取?

回答

-1

問題是tags不是一個字段,而是一個自定義管理器,它位於類級別並只是執行查詢。

我不確定這是否適用於自定義管理器,因爲它意味着產生類似查詢集的多對多字段等。但是,如果你使用的是django 1.4,你可以試試prefetch_related。它會做更多的查詢,批量化關係並緩存它們。

免責聲明又說:我不知道這是否適用於管理者

actions = Action.objects.select_related('reoccurance').filter(complete=False)\ 
       .prefetch_related('tags') 
+0

感謝您的輸入。免責聲明可能是正確的:'QuerySet'對象沒有'prefetch_related'屬性。我是否應該接受,我將有一個數據庫,以便在行動中採取行動? –

+0

我不能100%確定,因爲我從來沒有看過那個應用程序,但我的直覺告訴我,這隻能在字段上完成。現在,您可能可以在一個查詢中手動查詢所有標記,並使用該結果代替循環中每個對象的thr管理器。 – jdi

1

它可以使用prefetch_related檢索標籤,但你需要避開周圍的「標籤」的性質,因爲 - 正如jdi所說 - 這是一個自定義的經理,而不是真正的關係。相反,你可以這樣做:

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

不幸的是,action.tags.all在你的模板代碼將不使用預取的,並最終會做自己的查詢 - 所以你需要採取繞過的,而哈克步在「標籤」經理有太多:

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

(編輯:如果您收到「‘查詢集’對象有沒有屬性‘prefetch_related’」,這表明你在低於1.4版本的Django的,其中prefetch_related不可用。)