Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Query for a ManytoMany Field with Through in Django

I have a models in Django that are something like this:

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)

The idea being that there will be a set of fees associated with each Activity and Classification pair. Classification is like Student, Staff, etc.

I know that part works right.

Then in my application, I query for a set of Activities with:

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

Which returns a list of activities. I need to display in my template that list of Activities with their Fees. Something like this:

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

But I don't know of an easy way to get this info without a specific get query of the Fees object for each activity/class pair.

I hoped this would work:

activity.fee.all()

But that just returns the Classification Object. Is there a way to get the Fee Object Data for the Pair via the Activities I already queried?

Or am I doing this completely wrong?

like image 544
lovefaithswing Avatar asked Jan 28 '10 18:01

lovefaithswing


1 Answers

Considering michuk's tip to rename "fee" to "classification":

Default name for Fee objects on Activity model will be fee_set. So in order to get your prices, do this:

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

There's one thing though, as you can see you'll end up doing 1 SELECT on each activity object for fees, there are some apps that can help with that, for example, django-batch-select does only 2 queries in this case.

like image 159
Dmitry Shevchenko Avatar answered Oct 10 '22 16:10

Dmitry Shevchenko