使用select_related查询后的Django过滤器。

问题描述 投票:1回答:1

通过一个troble来过滤,我用于 select_related

这是我的购买模式。

class Purchase(models.Model):
    amount = models.FloatField(default=1)
    entry_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        related_name='ledger_entry_by',
    )
    is_cash = models.BooleanField(default=False)

这是我的消费模型

class Consume(models.Model):
    amount = models.FloatField(default=1)
    consumed_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        related_name='consume_entry_for',
    )

这是我的查询

user_wise_cost = User.objects.annotate(
            difference=ExpressionWrapper(
                Coalesce(Sum('ledger_entry_by__amount'), Value(0)) - Coalesce(Sum('consume_entry_for__amount'), Value(0)),
                output_field=FloatField()
            )
        )

上面的查询按照我的要求运行得很好。

我想只计算 cash 支付,我的意思是,如果一个条目 is_cash=True,将计算出

我的要求是。

例如,一个用户购买了500美元,但他消费了550美元,也就是说,他需要再支付50美元另一个用户购买了440美元,但他消费了400美元,也就是说,他将得到40美元的退款.另一个用户的例子可以是:一个用户没有购买任何东西,但他消费了300美元,所以他需要支付300美元.同样,如果一个用户没有购买任何东西或消费任何东西,但他的数据需要显示为0.

以上所有的要求都是通过该查询成功实现的,根本不存在问题,但目前,它计算的是两个 cashdue 但我希望只计算现金数额。

为此,我做了如下过滤。

user_wise_cost = User.objects.annotate(
            difference=ExpressionWrapper(
                Coalesce(Sum('ledger_entry_by__amount'), Value(0)) - Coalesce(Sum('consume_entry_for__number_of_meal'), Value(0)),
                output_field=FloatField()
            )
        ).filter(
            ledger_entry_by__is_cash=True
        )

它有一个问题,如果一个用户不购买任何东西或不消费任何东西,他的数据不显示。

谁能帮助我只计算现金金额?

django django-models django-rest-framework django-orm
1个回答
0
投票

与其过滤整个查询集,不如将过滤器传递给聚合表达式。

from django.db.models import Q

user_wise_cost = User.objects.annotate(
            difference=ExpressionWrapper(
                Coalesce(Sum('ledger_entry_by__amount', filter=Q(ledger_entry_by__is_cash=True)), Value(0)) - Coalesce(Sum('consume_entry_for__number_of_meal', filter=Q(ledger_entry_by__is_cash=True)), Value(0)),
                output_field=FloatField()
            )
        )
© www.soinside.com 2019 - 2024. All rights reserved.