【问题标题】:How to do group by on a different attribute and sum on a different attribute in Django?如何在Django中对不同的属性进行分组并对不同的属性求和?
【发布时间】:2019-05-28 19:56:29
【问题描述】:

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>

注意:为了使代码尽可能简短,我们特意删除了一些细节。如果缺少某些内容或会产生错误,请务必报告。

【问题讨论】:

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


    【解决方案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)
    

    【讨论】:

    • 这几乎是我所要求的正确替代品。鉴于问题中的示例,它似乎没有得到尚未进行任何交易的学生。这种情况下怎么办?
    • 我使用Student.objects.annotate(transactions_sum=Sum('studenttransaction__amount')).filter(Q(transactions_sum__lt=total_fees) | Q(studenttransaction=None)).distinct() 让它工作了。有没有更好的办法?
    【解决方案2】:

    这个查询应该对你有帮助

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

    【讨论】:

    • 作者想要返回 Student 查询集本身,而不是 values。他在描述中写道他不想使用values()
    猜你喜欢
    • 2023-04-06
    • 2021-03-23
    • 2017-01-23
    • 1970-01-01
    • 2017-11-06
    • 1970-01-01
    • 2018-05-23
    • 2013-06-18
    • 2018-10-24
    相关资源
    最近更新 更多