如何筛选ManyToMany对象的父属性



我是Django的新手,今天遇到了一个问题

我有两个型号,ProgramMember

型号.py

from django.db import models
from django.db.models import Sum
class Program(models.Model):
    name = models.CharField(max_length=200)
    fee = models.IntegerField(default=10)  # Arbitrary Property
class Member(models.Model):
    programs = models.ManyToManyField(Program, related_name='members')
    name = models.CharField(max_length=200)
    
    # I tried this but it gives me all of the sum of all the programs' fees :
    # fees_for_member = models.IntegerField(default=Program.objects.prefetch_related('members').aggregate(Sum('fee'))['fee__sum'])
    # This results in an error:
    # fees_for_member = programs.aggregate(Sum('fee'))['fee__sum']
     
    
    

每个程序都有一个fee,而Member有一个名为fees_for_member或仅为fees的IntegerField,其默认值是Member注册的所有Program fees的总和。

我的问题是,如何仅筛选member所在的Programs
我尝试过Program.objects.prefetch_related('members').aggregate(Sum('fee'))['fee__sum']),但它返回所有程序费用的总和

我也尝试过programs.aggregate(Sum('fee'))['fee_sum']
,但它给了我这个错误:
AttributeError: 'ManyToManyField' object has no attribute 'aggregate'

我能为此做些什么?我知道我遗漏了一些东西,但我不确定是什么。我花了几个小时搜索Django文档和SO,但我就是找不到答案,所以我很感激任何帮助。

您应该为fees_for_member定义一个属性,而不是一个字段,因为这必须动态计算:

class Member(models.Model):
    programs = models.ManyToManyField(Program, related_name='members')
    name = models.CharField(max_length=200)
    @property
    def fees_for_member(self):
        return self.programs.aggregate(models.Sum('fee'))['fee__sum']

这应该行得通。

解决方案2:

如果Program.fee也是一个属性,并且属性是python代码(而不是数据库中的值(,则不能使用数据库级别的操作。一个等效的解决方案是:

class Member(models.Model):
    programs = models.ManyToManyField(Program, related_name='members')
    name = models.CharField(max_length=200)
    @property
    def fees_for_member(self):
        return sum([p.fee for p in self.programs.all()])

关于此的一些文档:https://docs.djangoproject.com/en/3.0/topics/db/models/#model-方法

最新更新