Django:来自两个模型的多个COUNT

The*_*ing 5 sql django postgresql django-models

我正在尝试创建一个个人资料页面,显示分配给每个相应职业的矮人数量.我有4个职业,每个职业中有2个工作,当然还有很多矮人,每个人都有一份工作.如何计算每个职业中矮人的数量?我的解决方案是在HTML中硬化职业名称并对每个职业进行查询,但这似乎是一个过多的查询.

这是我"想要"看到的内容:

Unassigned: 3
Construction: 2
Farming: 0
Gathering: 1
Run Code Online (Sandbox Code Playgroud)

这是我的模特.我通过不直接将职业连接到我的矮人模型(他们通过他们的工作连接)来增加一些复杂性.

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
Run Code Online (Sandbox Code Playgroud)

编辑1 我的观点看起来像:

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

和模板:

{% for career in careers %}
    <li>{{ career.dwarf_set__count }}</li>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

错误是:

Cannot resolve keyword 'dwarf_set' into field. Choices are: id, job, name
Run Code Online (Sandbox Code Playgroud)

视图:

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

模板:

{% for career in careers reversed %}
    <li>{{ career.name }}: {{ career.dwarves_in_career }}</li>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

更好的解决方案

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

别忘了 from django.db.models import Count, Q

我对上述解决方案的喜爱之处在于,它不仅让失去了矮人工作的职业生涯发生了,而且即使是那些没有这个职业的职业也是我遇到的下一个问题.这是我对完整性的看法:

<ul>
{% for career in careers %}
    <li>{{ career.name }}: {{ career.dwarves_in_career }}</li>
{% endfor %}
</ul>
Run Code Online (Sandbox Code Playgroud)

Dan*_*man 1

这是你想要的吗?

from django.db.models import Count
Career.objects.annotate(Count('dwarf'))
Run Code Online (Sandbox Code Playgroud)

现在每个career对象都应该有一个dwarf__count属性。