Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter Many to Many relation in Django

I have this structure of model objects:

Class A:
b = models.ManyToManyField("B")
Class B:
c = models.ForeignKey("C")
d = models.ForeignKey("D")
Class C:
d = models.ForeignKey("D")

This is the query I'm trying to get:
I want to get all the B objects of object A, then in each B object to perform a comparison between the D object and the c.d object.

I know that simply move on the B collection with for loop and make this comparison. But I dived on the ManyToMany relation, then I noticed I can do the following:

bObjects = A.objects.all().b

q = bObjects.filter(c__d=None)

This is working, it gives me all the c objects with None d field. But when I try the following :

q = bObjects.filter(c__d=d)

It gives me d not defined, but d is an object like c in the object B.

What can be the problem? I'll be happy if you suggest further way to do this task. I generally I'm trying to write my query in a single operation with many to many sub objects and not using loops.

like image 723
Wasim Avatar asked Jan 13 '10 09:01

Wasim


People also ask

How do you do a many-to-many relationship in Django?

To define a many-to-many relationship, use ManyToManyField . What follows are examples of operations that can be performed using the Python API facilities. You can't associate it with a Publication until it's been saved: >>> a1.

How fetch data from many-to-many field in Django?

A ManyToManyField in Django is a field that allows multiple objects to be stored. This is useful and applicable for things such as shopping carts, where a user can buy multiple products. To add an item to a ManyToManyField, we can use the add() function.

How does many-to-many field work in Django?

A ManyToMany field is used when a model needs to reference multiple instances of another model. Use cases include: A user needs to assign multiple categories to a blog post. A user wants to add multiple blog posts to a publication.

Can we use multiple filters in Django?

I always assumed that chaining multiple filter() calls in Django was always the same as collecting them in a single call. The first queryset with the chained filter() calls joins the Inventory model twice effectively creating an OR between the two conditions whereas the second queryset ANDs the two conditions together.


1 Answers

q = bObjects.filter(c_d=d) //Give me d not defined. but d is an object like c in the object B.

Try this:

from django.db.models import F
q = bObjects.filter(c__d=F('d'))

As for the question from your comment below you can have 1 sql query instead of 100 in those ways:

1) if you can express your selection of A objects in terms of a query (for example a.price<10 and a.weight>20) use this:

B.objects.filter(a__price__lt=10, a__weight__gt=20, c__d=F('d'))

or this:

B.objects.filter(a__in=A.objects.filter(price__lt=10, weight__gt=20), c_d=F('d'))

2) if you just have a python list of A objects, use this:

B.objects.filter(a__pk__in=[a.pk for a in your_a_list], c__d=F('d'))
like image 194
Antony Hatchkins Avatar answered Oct 04 '22 21:10

Antony Hatchkins