qdot
qdot

Reputation: 6335

Django Many-To-Many filtering

Assume the following set of models:

class A(models.Model):
  pass

class B(models.Model):
  pass

class M2M(models.Model):
  a = models.ForeignKey(A)
  b = models.ForeignKey(B)

A way to filter (this is a part in the chain of a larger application) by some conditions on the links, in naive Django ORM is to do this:

def fun():
  as = A.objects.filter("some complex queryset") 

  m2ms = M2M.objects.filter("some complex B-dependent QS")

  return as.filter(id__in=[m.a_id for m in m2ms])  

But obviously this produces a rather awful query "id__in", and clearly executes as two queries.

Is there a better way to get Django to produce a proper join?

Upvotes: 0

Views: 944

Answers (2)

Daniel Roseman
Daniel Roseman

Reputation: 599610

You should explicitly declare a many-to-many field from A to B through M2M.

class A(models.Model):
  bs = models.ManyToManyField('B', through='M2M')

Now you can simply do:

A.objects.filter(condition_on_A='foo').filter(b__condition_on_b='bar')

Upvotes: 2

karthikr
karthikr

Reputation: 99620

You would be able to achieve this in a single query. For example, lets say you want to filter only those records which have a value greater than 50 on field x in the model B, you would do:

A.objects.filter("some-filter-criteria", m2m__b__x__gt=50)

You can read more on related name lookups here

Upvotes: 0

Related Questions