【问题标题】:Conditional annotate on django 1.8 querysetdjango 1.8 查询集上的条件注释
【发布时间】:2015-10-23 21:06:55
【问题描述】:

我的模型如下所示:

class MyStat(Model):
     metric = ForeignKey(MetricType) 
     source = ForeingKey(SourceType)

     total_units = IntegerField()
     metric_units = IntegerField()

     objects = MyQuerySet().as_manager()

查询在其一段代码中执行以下操作

rollup = self.order_by().values(source.name)\.
                 annotate(mu=Sum('metric_units'), tu=Sum('total_units'))

这很好用。但是,我想根据所使用的 metric 类型修改其中的一些注释。不知何故,创建一个注释略有不同的数据库端条件(下面的伪代码):

if metric is some_metric:
      .annotate(mu=.8*Sum('metric_units'))
else:
      .annotate(mu=Sum('metric_units'))

显然上述语法无效,但我想知道是否有办法设置我的查询集以在数据库端执行类似的操作

【问题讨论】:

    标签: python sql django django-models


    【解决方案1】:

    您可以使用Case 进行条件表达式。

    让我们进入注释部分。

    免责声明:此代码未经测试

    from django.db.models import Case, Value, When, FloatField, Sum
    
    ...annotate(mu=Case(When(metric=some_metric, then=Value(.8*Sum('metric_units')),
                        default=Value(Sum('metric_units')),
                        output_field=FloatField())))
    

    如果您需要匹配列表中的多个值,可以创建When 对象列表:

    whens = []
    for some_metric in some_metrics:
        whens.append(When(metric=some_metric, then=Value(some-value-here)))
    
    ...annotate(mu=Case(*whens, default=Value(Sum('metric_units')),
                                output_field=FloatField()))
    

    【讨论】:

    • 快速跟进,当您想要将条件应用于多个指标时,您如何做到这一点?我尝试做metric__in=some_metrics 没有成功。
    • @sedavidw 是some_metrics 列表吗?您是否尝试过此代码是否仅使用一个值来匹配条件 -> metric=some_metric
    • 这是一个列表,我尝试过使用单曲并且有效。查看文档,我似乎可以在 Case 中将 When 对象串在一起以实现该效果
    • 忘记了一个小错字,刚刚编辑了答案
    • 你说得对,它是default,谢谢。我希望这对你有所帮助。
    猜你喜欢
    • 2015-11-15
    • 2013-03-19
    • 2018-05-29
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2020-05-14
    • 2020-10-29
    • 1970-01-01
    相关资源
    最近更新 更多