Как считать объекты из базы данных, отфильтрованные по полю выбора в django? - PullRequest
0 голосов
/ 13 апреля 2020

У меня есть модель Porumbei, и у нее есть поле пола. В шаблоне я должен представить число Порумбеев каждого пола. Например: Мужской = x Порумбей, Женский = y Порумбей и Неизвестный = z Порумбей.

Моя модель

class Porumbei(models.Model):
    SEXE = [
        ('Mascul', 'Mascul'),
        ('Femelă', 'Femelă'),
        ('Pui', 'Pui')
    ]
    ...
    gender = models.CharField(max_length=6, choices=SEXE, db_index=True)
    ...

Всего у меня есть:

total = Porumbei.objects.count()

Ниже вот что у меня сейчас:

@staticmethod
def masculi(crescator=None):
    """ Numarul de masculi din sistem """
    mascul = Porumbei.objects.filter(gender="Mascul", is_active=True, crescator=crescator)
    return len(mascul)

@staticmethod
def femele(crescator=None):
    """ Numarul de femele din sistem """
    femela = Porumbei.objects.filter(gender="Femelă", is_active=True, crescator=crescator)
    return len(femela)

@staticmethod
def pui(crescator=None):
    """ Numarul de pui din sistem """
    pui = Porumbei.objects.filter(gender="Pui", is_active=True, crescator=crescator)
    return len(pui)

Эти функции дают мне то, что я хочу, но, с моей точки зрения, не очень хорошо оптимизированы. Это закончится тремя подобными запросами, как я видел на django панели инструментов отладки. У меня вопрос, как я могу получить количество каждого пола только в одном запросе. Возможно ли с помощью другого метода или эта функция может быть оптимизирована для выполнения одного запроса в базе данных? Я должен упомянуть, что с числом каждого пола должны быть выполнены арифметические операции c. Например, сколько всего составляет каждый пол. Заранее спасибо!

1 Ответ

3 голосов
/ 13 апреля 2020

Вы можете использовать values() и annotate() для запуска поля GROUP BY на gender, а затем получить счетчик.

from django.db.models import Count

gender_count = Porumbei.objects.values('gender').annotate(count=Count('gender')).order_by()

order_by() является необязательным предложением, но его следует добавить, когда для Model определен порядок по умолчанию. From docs :

Поля, которые упоминаются в части order_by() набора запросов (или которые используются в порядке по умолчанию для модели), используются при выборе выходных данных. данные, даже если они не указаны в вызове values(). Эти дополнительные поля используются для группировки «похожих» результатов вместе, и в противном случае идентичные строки результатов могут казаться отдельными. Это проявляется, в частности, при подсчете вещей.

Добавление order_by() в конце очищает любой порядок по умолчанию.

Как я могу сделать это в шаблоне?

gender_count словарь будет содержать gender значений в качестве ключа и соответствующий счетчик в качестве значения.

Для рендеринга gender_count в шаблоне вы можете выполнять итерации по dict.

{% for gender, count in gender_count.items %} 
    <p>{{gender}}: {{count}}</p>
{% endfor %}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...