在Django中使用Through查询ManytoMany字段

时间:2010-01-28 18:35:46

标签: django django-models many-to-many

我在Django中有一个类似的模型:

class Classification(models.Model):
  name = models.CharField(choices=class_choices)
  ...

class Activity(models.Model):
  name = models.CharField(max_length=300)
  fee = models.ManyToManyField(Classification, through='Fee')
  ...

class Fee(models.Model):
  activity = models.ForeignKey(Activity)
  class = models.ForeignKey(Classification)
  early_fee = models.IntegerField(decimal_places=2, max_digits=10)
  regular_fee = models.IntegerField(decimal_places=2, max_digits=10)

这个想法是每个活动和分类对都会有一系列费用。分类就像学生,员工等。

我知道那部分是正确的。

然后在我的应用程序中,我查询了一组活动:

activities = Activity.objects.filter(...)

返回活动列表。我需要在我的模板中显示活动列表及其费用。像这样:

Activity Name
Student Early Price - $4
Student Regular Price - $5
Staff Early Price - $6
Staff Regular Price - $8

但是我不知道如果没有针对每个活动/类对的Fees对象的特定get查询,获取此信息的简单方法。

我希望这会奏效:

activity.fee.all()

但这只是返回分类对象。有没有办法通过我已经查询的活动获得对的费用对象数据?

或者我完全错了吗?

2 个答案:

答案 0 :(得分:6)

考虑到michuk的提示将“费用”重命名为“分类”:

活动模型上费用对象的默认名称将为fee_set。所以为了得到你的价格,请这样做:

for a in Activity.objects.all():
    a.fee_set.all() #gets you all fees for activity

但是有一件事,因为你可以看到你最终会在每个活动对象上做一次SELECT以获得费用,有些应用程序可以帮助解决这个问题,例如,django-batch-select只进行2次查询这种情况。

答案 1 :(得分:2)

首先,我认为你把你的领域命名为错误。这样:

fee = models.ManyToManyField(Classification, through='Fee')

应该是:

classifications = models.ManyToManyField(Classification, through='Fee')

因为ManyToManyField引用了相关对象的列表。

通常,ManyToManyField,AFAIK只是一个django快捷方式,可以轻松获取所有相关对象(在您的情况下为分类),关联表对模型是透明的。您想要的是关联表(在您的情况下为费用)透明。

所以我要做的是从Activity中删除ManyToManyField字段,只需获得与活动相关的所有费用。然后,如果您需要为每项费用进行分类,请单独进行分类。