Django ORM сумма всех значений полей модельного класса - PullRequest
0 голосов
/ 25 апреля 2020

Это мои модели:

#models.py
class Bill(models.Model):
    user =  models.OneToOneField(
        User,
        on_delete=models.CASCADE,

    )
    flat_rent = models.DecimalField(
        max_digits=6,
        decimal_places=2,
        null=True,
        blank=True
    )
    gas = models.DecimalField(
        max_digits=6,
        decimal_places=2,
        null=True,
        blank=True
    )

Я хочу вычислить общую сумму полей этой модели, используя одну строку запроса. Я знаю ниже, это способ сделать это. Но я не хочу его использовать.

bill = Bill.objects.get(--------)
total = bill.gas + bill.flat_rent

Я думаю, что это плохая практика, потому что у меня в этой модели более 20 полей, и я хочу вычислить сумму всех этих полей.

Может ли кто-нибудь помочь мне с этим делом?

Ответы [ 4 ]

0 голосов
/ 25 апреля 2020

Это вернет сумму всех указанных полей

total = [ sum(item) for item in Bill.objects.filter(user='user').values_list('flat_rent', 'gas', 'next_field', ...)]

Примечание: Это вернет список в конце.

РЕДАКТИРОВАТЬ: Если у вас слишком много полей, чтобы упомянуть, используйте defer, чтобы исключить ненужные поля и получить все оставшиеся поля.

Bill.objects.filter(user='user').defer('unwanted_field')

Если набор запросов всегда соответствует / возвращает только одну запись, тогда это будет работать

sum(Bill.objects.filter(user='user').values_list('gas', 'flat_rent').first())
0 голосов
/ 25 апреля 2020

Обычный способ - создать метод в вашей модели.

class Bill(models.Model):
   ...

   def get_total(self):
       return self.gas + self.flat_rent

Тогда, если вы пишете код, вы можете просто использовать obj.get_total()
Или в строке:

try:
    total = Bill.objects.get(pk=<some_pk>).get_total()
except Bill.DoesNotExist:
    total = None
0 голосов
/ 25 апреля 2020

Вы можете суммировать их с помощью аннотирования и F выражений

from django.db.models import F

Bill.objects.annotate(total = F('gas') + F('flat_rent'))
0 голосов
/ 25 апреля 2020

Вы можете использовать F () выражения, подобные этому:

from django.db.models import F
from functools import reduce
from operator import add

field_names = [field.name for field in Bill._meta.get_fields()]
# remove unwanted fields from field_names, if any
expr = reduce(add, (F(field) for field in field_names))
Bill.objects.filter(---).annotate(total=expr).values('total')
...