属性字段上的Django注释
我正在使用属性字段上的Django注释,django,django-models,django-queryset,Django,Django Models,Django Queryset,我正在使用Django 2.0和Django REST框架 我有一个像下面这样的模型 class Contact(models.Model): first_name = models.CharField(max_length=100) class AmountGiven(models.Model): contact = models.ForeignKey(Contact, on_delete=models.PROTECT) amount = models.FloatFi
Django 2.0
和Django REST框架
我有一个像下面这样的模型
class Contact(models.Model):
first_name = models.CharField(max_length=100)
class AmountGiven(models.Model):
contact = models.ForeignKey(Contact, on_delete=models.PROTECT)
amount = models.FloatField(help_text='Amount given to the contact')
@property
def total_payable(self):
return self.amount
@property
def amount_due(self):
returned_amount = 0
for returned in self.amountreturned_set.all():
returned_amount += returned.amount
return self.total_payable - returned_amount
class AmountReturned(models.Model):
amount_given = models.ForeignKey(AmountGiven, on_delete=models.CASCADE)
amount = models.FloadField()
我必须分别获得给定金额
和到期金额
的前10名联系人
在我看来,我正在像这样过滤数据
@api_view(http_method_names=['GET'])
def top_ten(request):
filter_type = request.query_params.get('type', None)
if filter_type == 'due':
# query for due type
elif filter_type == 'given':
qs = Contact.objects.filter(
user=request.user
).values('id').annotate(
amount_given=Sum('amountgiven__amount')
).order_by(
'-amount_given'
)[:10]
graph_data = []
for q in qs:
d = {}
contact = Contact.objects.get(pk=q['id'])
d['contact'] = contact.full_name if contact else 'Unknown'
d['value'] = q['amount_given']
graph_data.append(d)
return Response(graph_data)
else:
raise NotFound('No data found for given filter type')
类型
查询可以是到期或给定
给定的类型的代码工作正常,因为所有字段都在数据库中。但是如何根据虚拟字段筛选due
type?
我要做的是通过
联系人注释到期金额属性组的总和,您不能基于@property
进行筛选
就我对您的问题的正确理解而言,您可以将相关的给定金额
和未重试金额
的总和相加,然后计算到期金额
字段,该字段保留减去字母和前者的结果
查询:
from django.db.models import Sum, Value
from django.db.models.functions import Coalesce
Contact.objects.filter(
amountgiven__amount__gt=0
).annotate(
due=Sum('amountgiven__amount') - Coalesce(Sum('amountgiven__amountreturned__amount'), Value(0))
).order_by('-due').values_list('due', 'id')
将返回:
但是,使用此解决方案,您无法在一个联系人中区分多个给定的
。你得到的是全局性的结果
如果要按给定的数量拆分到期值,请按如下注释:
AmountGiven.objects.annotate(
due=Sum('amount') - Coalesce(Sum('amountreturned__amount'), Value(0))
).order_by('-due').values_list('due', 'contact__id', 'id')
返回
<QuerySet [
{'contact__id': 3, 'id': 3, 'due': 2500.0},
{'contact__id': 1, 'id': 1, 'due': 1750.0},
{'contact__id': 2, 'id': 2, 'due': 1500.0},
{'contact__id': 1, 'id': 4, 'due': 350.0},
{'contact__id': 1, 'id': 5, 'due': 350.0}
]>
参考资料