views:

533

answers:

1

Hi all,

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 make 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) //Give 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.

Thanks in advance,

A: 

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'))
Antony Hatchkins
Thanks allot, It works. One more question : If I have list of objects of the main object A. Can I do the query you wrote with one line and not iterate over the A list and do the same thing.Simply I want to save hits to the DB id I have 100 of A then I have to make the query 100 time.Thanks
Wasim
Wasim, add .select_related('a') to the tend of your query
Pydev UA
Thank you very much , it works.On note : if I write B.objects.filter(a__in=A.objects.filter(price__lt=10, weight__gt=20).query,c_d=F('d')) . It throws an error SQL Error: Operand should contain 1 column(s).I looked at the generated SQL , then instead of .query I replaced it with .all and this solved the problem.Thanks again.
Wasim
You could as well remove `.query` and it would work. Updated my answer.
Antony Hatchkins
You can accept the answer if you find it helpful.
Antony Hatchkins