如何在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
相关产品推荐
相关产品推荐

