Я пытаюсь создать страницу профиля, которая показывает количество карликов, которые присвоены каждой соответствующей карьере. У меня есть 4 карьеры, 2 задания в рамках каждой той карьеры и конечно многих карликов, что у каждого есть единственное задание. Как я могу получить количество числа карликов в каждой той карьере? Моим решением были к хардкору карьерные имена в HTML и сделать запрос для каждой карьеры, но это походит на чрезмерное количество запросов.
Вот то, что я "хочу" видеть:
Unassigned: 3
Construction: 2
Farming: 0
Gathering: 1
Вот мои модели. Я добавляю некоторую сложность, не подключая Карьеру непосредственно к моей модели Dwarves (они соединились их заданиями).
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>
Делает ли это то, что вы хотите?
from django.db.models import Count
Career.objects.annotate(Count('dwarf'))
Теперь каждый объект
должен иметь DWARF__COUNT
свойство.
ORM Django не сделает этот Uber-Simple. Простой способ - сделать что-то вроде:
для карьеры в карьере .Objects.all (): Carea.dwarf_set.all (). COUNT ()
, который будет выполнять 1 запрос для каждой задания (O (N) сложности).
Вы можете попытаться ускорить это, используя функцию агрегации Django , но я не совсем уверен, что это будет делать то, что вам нужно. Вы должны посмотреть.
Третий вариант - использовать пользовательский SQL, который будет абсолютно получить работу. Вы просто должны написать его и поддерживать его как ваше приложение растет и меняется ...
Разве вы не можете просто получить счет, сгруппированный по карьере? И выполните внешнее соединение, если вам нужны нулевые строки тоже.