2010-01-25 25 views
5

我試圖創建一個個人資料頁面,顯示分配給每個相應職業的矮人數量。我有4個職業,每個職業有2個職位,當然還有許多矮人,每個職業都有一份工作。我如何計算每個職業中的矮人數量?我的解決方案是在HTML中強化職業名稱並對每個職業進行查詢,但這似乎是一個過多的查詢。Django:來自兩個模型的多個COUNTs

這裏就是我 「想」 看到:

Unassigned: 3 
Construction: 2 
Farming: 0 
Gathering: 1 

這裏是我的模型。我通過不將職業直接連接到我的矮人模型(他們通過他們的工作連接)來增加一些複雜性。

from django.contrib.auth.models import User 
from django.db import models 

class Career(models.Model): 
    name = models.CharField(max_length = 64) 

    def __unicode__(self): 
     return self.name 

class Job(models.Model): 
    career = models.ForeignKey(Career) 
    name = models.CharField(max_length = 64) 
    career_increment = models.DecimalField(max_digits = 4, decimal_places = 2) 
    job_increment = models.DecimalField(max_digits = 4, decimal_places = 2) 

    def __unicode__(self): 
     return self.name 

class Dwarf(models.Model): 
    job = models.ForeignKey(Job) 
    user = models.ForeignKey(User) 
    created = models.DateTimeField(auto_now_add = True) 
    modified = models.DateTimeField(auto_now = True) 
    name = models.CharField(max_length = 64) 

    class Meta: 
     verbose_name_plural = 'dwarves' 

    def __unicode__(self): 
     return self.name 

編輯1個 我的觀點看起來像:

def fortress(request): 
    careers = Career.objects.annotate(Count('dwarf_set')) 
    return render_to_response('ragna_base/fortress.html', {'careers': careers}) 

和模板:

{% for career in careers %} 
    <li>{{ career.dwarf_set__count }}</li> 
{% endfor %} 

的錯誤是:

Cannot resolve keyword 'dwarf_set' into field. Choices are: id, job, name 

解決方案

觀點:

def fortress(request): 
    careers = Career.objects.all().annotate(dwarfs_in_career = Count('job__dwarf')) 
    return render_to_response('ragna_base/fortress.html', {'careers': careers}) 

模板:

{% for career in careers reversed %} 
    <li>{{ career.name }}: {{ career.dwarves_in_career }}</li> 
{% endfor %} 

更好的解決方案

careers = Career.objects.filter(Q(job__dwarf__user = 1) | Q(job__dwarf__user__isnull = True)) \ 
    .annotate(dwarves_in_career = Count('job__dwarf')) 

不要忘記from django.db.models import Count, Q

我喜歡上述解決方案的是,它不僅返回了矮人工作的職業,甚至還有沒有任何職業,這是我遇到的下一個問題。這是我對完整性的看法:

<ul> 
{% for career in careers %} 
    <li>{{ career.name }}: {{ career.dwarves_in_career }}</li> 
{% endfor %} 
</ul> 

回答

1

這是做你想做的嗎?

from django.db.models import Count 
Career.objects.annotate(Count('dwarf')) 

現在每個career對象應該有一個dwarf__count財產。

+0

不錯!我仍然繼續出現錯誤:無法將關鍵字'dwarf_set'解析爲字段。選擇是:身份證,工作,名稱 但我試着不同的事情。 – TheLizardKing 2010-01-25 09:59:27

+0

如果我的矮人模型與我的職業模式直接相關,但我選擇通過我的工作模式連接兩者以允許改變職業生涯,我覺得這會起作用。 – TheLizardKing 2010-01-25 10:23:30

1

難道你不能只按職業分組計數嗎?如果您需要返回零行,則執行外連接。

2

Django的ORM不會讓這個超級簡單。最簡單的方法是做一樣的東西:職業

在Career.objects.all(): career.dwarf_set.all()COUNT()

,將執行1個查詢每個職位(O (n)複雜性)。

您可以嘗試通過使用Django's Aggregation feature來加快速度,但我不完全確定它是否能夠滿足您的需求。你必須看一看。

第三個選擇是使用自定義SQL,這將完成工作。你只需要編寫它,並保持它隨着你的應用程序的增長和變化...