class Category(BaseEntity):
""" to categorise the expense """
name = models.CharField(
max_length=80,
validators=[
RegexValidator(
regex='^[a-zA-Z\s]*$',
message='name should contain only alphabets',
code='invalid_name'
),
]
)
description = models.CharField(
max_length=250,
validators=[
RegexValidator(
regex='^[a-zA-Z\s]*$',
message='name should contain only alphabets',
code='invalid_name'
),
],
null = True,
blank = True
)
parent_category = models.ForeignKey(
'self',
related_name = 'child_categories',
on_delete = models.CASCADE,
null = True,
blank = True
)
class Expense(BaseEntity):
"""covers all the expenses"""
SEGMENT_CHOICES=(
('RENTALS', 'Rentals'),
('MIXING', 'Mixing'),
('ALBUMS', 'Albums'),
('SALES', 'Sales'),
)
amount = models.IntegerField(
default=500,
validators=[
MinValueValidator(
0,
message = 'Amount should be greater than 0'
),
MaxValueValidator(
100000,
message = 'Amount should be less than 100000'
),
]
)
category = models.ForeignKey(
'accounting.Category',
related_name='expenses',
on_delete=models.CASCADE,
null = True,
blank = True
)
date = models.DateField(
verbose_name='spending date'
)
description = models.CharField(
max_length=250,
validators=[
RegexValidator(
regex='^[a-zA-Z\s]*$',
message='name should contain only alphabets',
code='invalid_name'
),
],
null = True,
blank = True
)
event = models.ForeignKey(
'booking.Event',
related_name='event_expenses',
blank = True,
null =True,
on_delete=models.CASCADE
)
business_segment= models.CharField(
max_length =15,
choices = SEGMENT_CHOICES,
default = 'RENTALS',
)
查询:
expense_category = Expense.objects.values('category__name').annotate(total=Sum('amount'))
输出如下所示:
<QuerySet [{'category__name': 'Diesel', 'total': 2000}, {'category__name': 'Diesel', 'total': 2000}, {'category__name': 'Diesel', 'total': 2000}, {'category__name': 'Diesel', 'total': 3000}, {'category__name': 'web live', 'total': 1600}, {'category__name': 'Diesel', 'total': 2200}, {'category__name': 'Diesel', 'total': 1000}, {'category__name': 'Diesel', 'total': 1000}, {'category__name': 'Diesel', 'total': 500}, {'category__name': 'Diesel', 'total': 1600}, {'category__name': 'Diesel', 'total': 2500}, {'category__name': 'Bills', 'total': 200}, {'category__name': 'Diesel', 'total': 5600}]>
即使Diesel有许多条目,也无法正确分组。我在查询中缺少任何内容吗?我不喜欢为此做列表处理,我希望通过查询方法来完成。列表逻辑只会使事情复杂化,浪费处理能力
答案 0 :(得分:1)
Category
个对象(具有额外的属性)首先,我认为从Category
对象进行查询更有意义,那么也许我们甚至不需要执行适当的分组依据,例如:
Category.objects.annotate(total=Sum('expenses__amount'))
这将导致一个QuerySet
,其中每个Category
都有一个额外的属性.total
。这样做可能更好,因为从那时起您就可以访问Category
的所有属性,并且它的行为类似于Category
。
QuerySet
的字典如果只希望使用QuerySet
字典,则需要在末尾添加.order_by(..)
属性(是的,我知道这听起来很奇怪),例如:
qs = Category.objects.values(
'name'
).annotate(
total=Sum('expenses__amount')
).order_by('name')
这将导致:
<QuerySet [
{ 'name': 'bar', 'total': 14.0 }
{ 'name': 'foo', 'total': 25.0 }
]>
但是请注意,如果两个类别具有 same 名称,则它们将加起来,这可能并不理想。