Django 使用某些字段的最新值注释查询集

Posted

技术标签:

【中文标题】Django 使用某些字段的最新值注释查询集【英文标题】:Django annotated queryset with latest values for some fields 【发布时间】:2021-05-09 01:27:57 【问题描述】:

我有一个存储一些营销业绩的模型:

class DailyPerformance(models.Model):

    class Meta:
        unique_together = ('route_hash_value', 'datetime_tz')
        ordering = ('-datetime_tz',)

    route_hash_value = models.CharField(max_length=255, db_index=True, editable=False)
    datetime_tz = models.DateTimeField(db_index=True, editable=False)
    network = models.ForeignKey('administration.Network', on_delete=models.PROTECT, null=True)
    account = models.ForeignKey('administration.Account', on_delete=models.SET_NULL, null=True)

    # Properties
    budget = models.FloatField(null=True, db_index=True)
    bid = models.FloatField(null=True, db_index=True)
    status = models.CharField(max_length=255, null=True, db_index=True)

    # METRICS
    cost_amount = models.FloatField(null=True, db_index=True)
    impressions = models.IntegerField(null=True, db_index=True)
    clicks_in = models.IntegerField(null=True, db_index=True)
    clicks_out = models.IntegerField(null=True, db_index=True)
    revenue_amount_net = models.FloatField(null=True, db_index=True)
    _profit = models.FloatField(null=True, db_index=True)
    _roi = models.FloatField(null=True, db_index=True)
    _ctr = models.FloatField(null=True, db_index=True)

我需要为 drf ModelViewset 生成一个查询集,它聚合数字指标并获取字段的最后值:出价、预算和状态。

类似这样的:

class DailyPerformanceHViewSet(viewsets.ReadOnlyModelViewSet):

    def get_queryset(self):
        queryset = DailyPerformance.objects.values(
            'route_hash_value',
            'datetime_tz',
            'network',
            'account',
        ).annotate(
            cost_amount=Round(Sum('cost_amount'), 3),
            revenue_amount_net=Round(Sum('revenue_amount_net'), 3),
            impressions=Sum('cost_impressions', output_field=FloatField()),
            clicks_in=Sum('cost_clicks_in', output_field=FloatField()),
            clicks_out=Sum('cost_clicks_out', output_field=FloatField()),
            _profit=Round(Sum('_profit'), 3),
            _roi=Round(F('_profit') / F('cost_amount'), 3),
            _ctr=Round(F('clicks_out') / F('clicks_in'), 3),
            ### 
            budget=...,      # <== LATEST BUDGET ORDERED BY -datetime_tz 
            bid=...,      # <== LATEST BID ORDERED BY -datetime_tz 
            status=...,    # <== LATEST STATUS ORDERED BY -datetime_tz 
        )

        return queryset

但我真的不知道该怎么做

【问题讨论】:

【参考方案1】:

您好,您可能需要执行子查询以将最新预算等注释到您的查询集上。

# this will create a query to select DailyPerformance objects and order by date.
last_budget_entry = DailyPerformance.objects.filter(id=OuterRef('pk')).order_by('-datetime_tz)

# annotate your queryset with the query first item in the query(since its the newest). 
queryset.annotate(latest_budget=Subquery(last_budget_entry.values('id')[:1]))

这将创建一个子查询,它将评估“last_budget_entry”查询中第一个元素的 id。 (此值将由 Outeref 提供)并将 id 的值注释到查询集。

#to annotate the value of the budget field 
queryset.annotate(latest_budget=Subquery(last_budget_entry.values('budget')[:1]))

您可以使用 outerref 对查询进行排序,以选择要在新查询集上注释的值 在此处阅读查询表达式和子查询 https://docs.djangoproject.com/en/3.1/ref/models/expressions/#subquery-expressions

【讨论】:

以上是关于Django 使用某些字段的最新值注释查询集的主要内容,如果未能解决你的问题,请参考以下文章

Django 查询集注释与日期时间计算

与 django 查询集注释中的先前对象的区别

为查询集注释排名字段的正确方法

(转)解决swagger跨项目或跨程序集注释不显示问题

TFS 签入时,提示“变更集注释策略 中的内部错误……”

如何在带注释的 Django 查询集结果上列出字段值?