如何在Django中对不同的属性进行分组并求和?

时间:2019-01-02 05:45:04

标签: django foreign-keys django-admin django-queryset

models.py

class Student(models.Model):
    total_fees = models.PositiveIntegerField(blank=False)
    roll_number = models.PositiveIntegerField(blank=False)

class StudentTransaction(models.Model):
    student = models.ForeignKey(Student, on_delete=models.CASCADE, blank=False)
    amount = models.PositiveIntegerField(blank=False)
    timestamp = models.DateTimeField(auto_now_add=True, blank=True)

admin.py

class StudentTransactionModelAdmin(admin.ModelAdmin):
    list_display = ['__str__', 'time', 'amount']

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'student':
            x = StudentTransaction.objects.order_by().annotate(Sum('amount')).filter(amount__sum__lt=student__total_fees)
            kwargs["queryset"] = [i.student for i in x]
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

在进行annotate时,我想获取功能formfield_for_foreignkey中每个学生的所有交易金额的总和。我需要实际的Student对象,因此无法使用values来完成。

为简化起见,请考虑存在3个Student对象。其中之一进行了2笔交易,另一笔进行了4笔交易,而第三笔没有进行任何交易。每个学生的交易金额之和不超过该学生的total_feesformfield_for_foreignkey应该返回所有尚未付款的Student对象。条件是:

sum(<all transactions of each student>) is less than <total_fees of that student>

注意:故意删除了一些细节,以使代码尽可能短。如果缺少某些东西或将产生错误,请进行报告。

2 个答案:

答案 0 :(得分:1)

只要您需要返回Students而不是StudentTransaction,您可以这样做:

students = Student.objects.annotate(transactions_sum=Sum('studenttransaction__amount')).filter(transactions_sum__lt=total_fees)

如果将代码放入您的方法,则它看起来像:

def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'student':
            students = Student.objects.annotate(transactions_sum=Sum('studenttransaction__amount')).filter(transactions_sum__lt=total_fees)
            kwargs["queryset"] = students
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

答案 1 :(得分:0)

此查询应为您提供帮助

StudentTransaction.objects.annotate(Sum('amount')).values('student').filter(amount__sum__lte=total_fees)