views:

147

answers:

3

Suppose my model looks like this:

class Farm(models.Model):
   name = ...

class Tree(models.Model):
   farm = models.ForeignKey(Farm)

...and I get a QuerySet of Tree objects. How do I determine what farms are represented in that QuerySet?

+3  A: 

There might be a better way to do it with the Django ORM and keep it lazy but you can get what you want with regular python (off the top of my head):

>>> set([ t.farm for t in qs ])
skyl
That was what I was about to put in.
Mez
That'll work since I have to iterate over them anyway later on. Thanks.
magneticMonster
The square brackets aren't necessary here, you can use: `set(t.farm for t in qs)`
Ben James
A: 

Here is a way to have the database do the work for you:

farms = qs.values_list('farm', flat=True).distinct() 
#values_list() is new in Django 1.0

return value should evaluate to something like:

(<Farm instance 1>, <Farm instance5>)

were farms will be those that have trees in that particular query set.

For all farms that have trees, use qs = Tree.objects

Keep in mind that if you add order_by('some_other_column') then distinct will apply to the distinct combinations of 'farm' and 'some_other_column', because other column will also be in the sql query for ordering. I think it's a limitation (not an intended feature) in the api, it's described in the documentation.

Evgeny
so this could be qs.values('farm').distinct()? Does this return a flat list or a qs or what? .. should look in the docs...
skyl
That will give you ALL the farms. The question ask for the farms related the the tree qs only.
Juanjo Conti
Just replace `Tree.objects` with the appropriate Tree queryset and it will not give you all the farms.
Ben James
so then qs.values_list('farm', flat=True).distinct() would work too to create a flat list or I have broken it?
skyl
+3  A: 

http://docs.djangoproject.com/en/dev/ref/models/querysets/#in

Farm.objects.filter(tree__in=TreeQuerySet)
nice, I think that is a well-performing way to go. Especially for a very large Tree qs? -- compared to my 'bring it into memory' way.
skyl