Django聚合问题

时间:2018-06-20 09:14:36

标签: django django-models

在通过Django的ORM进行聚合方面,我有一个小问题。我的模型草图非常简单,带有一些自定义字段类型(但这些类型与问题无关):

字段类型

class MoneyField(models.DecimalField):

    def __init__(self, *args, **kwargs):
        kwargs['null'] = True
        kwargs['blank'] = True
        kwargs['max_digits'] = 15
        kwargs['decimal_places'] = 2
        super().__init__(*args, **kwargs)

class RevenueField(MoneyField):

    def __init__(self, *args, **kwargs):
        kwargs['validators'] = [MinValueValidator(0)]
        kwargs['null'] = True
        kwargs['blank'] = True
        super().__init__(*args, **kwargs)

class WeakTextField(models.CharField):

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = 200
        kwargs['null'] = True
        kwargs['blank'] = True
        super().__init__(*args, **kwargs)

class NameField(WeakTextField):

    def __init__(self, *args, **kwargs):
        kwargs['unique'] = True
        super().__init__(*args, **kwargs)

class YearField(models.PositiveIntegerField):

    def __init__(self, *args, **kwargs):
        kwargs['validators'] = [
            MinValueValidator(1900),
            MaxValueValidator(2100),
        ]
        kwargs['null'] = True
        kwargs['blank'] = True
        super().__init__(*args, **kwargs)

class WeakForeignKey(models.ForeignKey):

    def __init__(self, *args, **kwargs):
        kwargs['null'] = True
        kwargs['blank'] = True
        kwargs['on_delete'] = models.SET_NULL
        super().__init__(*args, **kwargs)

模型实体

class Company(models.Model):

    registration_number = NameField(_('Registration number')) # custom field, defined above
    name = NameField(_('Name'))
   ...
   ..
   .

class Financial(models.Model):

    financial_year = YearField(_('Financial year'))
    company = WeakForeignKey(to='Company', verbose_name=_('Company'))
    revenue = RevenueField(_('Revenue'))
   ...
   ..
   .

    class Meta:
        unique_together = (('financial_year', 'company'),)

我的目标是使用QuerySet编写这样的查询:

SELECT financial_year, SUM(revenue) 
FROM financial
GROUP BY financial_year

据我所知,ORM应该这样完成:

qs = Financial.objects.values('financial_year').annotate(Sum('revenue'))

但是,如果我打印出SQL查询,则在Group By语句之后会有一个额外的"data_manager_company"."name"字段:

SELECT 
    "data_manager_financial"."financial_year", 
    CAST(SUM("data_manager_financial"."revenue") AS NUMERIC) AS "revenue__sum"
FROM "data_manager_financial" 
LEFT OUTER JOIN "data_manager_company" 
ON ("data_manager_financial"."company_id" = "data_manager_company"."id") 
GROUP BY 
    "data_manager_financial"."financial_year", 
    "data_manager_company"."name"
ORDER BY "data_manager_company"."name" 
ASC, "data_manager_financial"."financial_year" ASC

恐怕这个问题与金融实体的独特约束有关。当然,可以通过原始SQL或通过财政年度字段的单独实体解决问题,但我不喜欢它们。你有什么想法吗?

非常感谢!

Gallusz

1 个答案:

答案 0 :(得分:1)

我认为这更多是因为您注释每个单独的对象。因此,结果相同 'financial_year'在您的查询中将发生多次次。

这些年来,您可以将 .order_by(..) 声明“ 折叠”成一个条目,我听起来很奇怪:

qs = Financial.objects.values(
    'financial_year'
).annotate(
    Sum('revenue')
).order_by(
    'financial_year'
)

因此,在这里,我们指示Django仅使用'financial_year'作为石斑鱼,因此在每个Sum(..)的{​​{1}}上使用'revenue'