You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django的values查询中调用模型的balance属性?

问题:如何在Django的values查询中获取模型的balance属性值用于Union操作

你需要通过values查询获取Bills模型的balance属性值,以便后续执行union操作。当前Bills模型定义如下:

class Bills(models.Model):
    salesPerson = models.ForeignKey(User, on_delete = models.SET_NULL, null=True)
    purchasedPerson = models.ForeignKey(Members, on_delete = models.PROTECT, null=True)
    cash = models.BooleanField(default=True)
    totalAmount = models.IntegerField()
    advance = models.IntegerField(null=True, blank=True)
    remarks = models.CharField(max_length = 200, null=True, blank=True)
    created = models.DateTimeField(auto_now_add=True)
    update = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-update', '-created']

    def __str__(self):
        return str(self.purchasedPerson)
    
    @property
    def balance(self):
        return 0 if self.cash == True else self.totalAmount - self.advance

直接遍历查询集可以正常获取balance属性,但因为要和其他模型做union操作,必须使用values查询固定字段。当前的查询语句是:

bill_trans = Bills.objects.filter(purchasedPerson__id__contains = pk,
                                 cash = False).values('purchasedPerson',
                                     'purchasedPerson__name', 'cash',
                                     'totalAmount', 'id', 'created')

需要把其中的totalAmount替换为balance,该如何实现?


解决方案

因为balance是模型的属性方法(用@property装饰),无法直接在values中引用,需要用Django的annotate结合数据库函数来在数据库层面计算出balance的值,之后就能在values中调用这个注解字段。

步骤1:导入必要的数据库函数

需要用到Case、When和Value这些函数来实现和balance属性相同的逻辑:

from django.db.models import Case, When, Value, IntegerField, F

步骤2:用annotate注解balance字段

在查询中添加annotate,把balance的计算逻辑迁移到数据库层面:

bill_trans = Bills.objects.filter(
    purchasedPerson__id__contains=pk,
    cash=False
).annotate(
    balance=Case(
        When(cash=True, then=Value(0)),
        default=F('totalAmount') - F('advance'),
        output_field=IntegerField()
    )
).values(
    'purchasedPerson',
    'purchasedPerson__name',
    'cash',
    'balance',  # 这里替换原来的totalAmount
    'id',
    'created'
)

简化优化

因为你的过滤条件已经指定了cash=False,可以直接简化注解逻辑,不需要再判断cash的值,提升查询效率:

bill_trans = Bills.objects.filter(
    purchasedPerson__id__contains=pk,
    cash=False
).annotate(
    balance=F('totalAmount') - F('advance'),
    output_field=IntegerField()
).values(
    'purchasedPerson',
    'purchasedPerson__name',
    'cash',
    'balance',
    'id',
    'created'
)

用annotate生成的字段可以直接在values中使用,查询结果会包含balance字段,完全满足后续union操作的要求。


内容的提问来源于stack exchange,提问作者ClownBunny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 19:10:18