Reputation: 6335
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
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
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