views:

284

answers:

3

Hi,

I have a model Foo which have a ForeignKey to the User model.

Later, I need to grab all the User's id and put then on a list

foos = Foo.objects.filter(...)

l = [ f.user.id for f in foos ]

But when I do that, django grabs the whole User instance from the DB instead of giving me just the numeric user's id, which exist in each Foo row.

How can I get all the ids without querying each user or using a select_related?

Thanks

A: 

Nevermind... I´m not sure why this didn´t work before when I tried, but this is how to do:

l = [ f.user_id for f in foos ]
Tiago
+4  A: 

Use queryset's values() function, which will return a list of dictionaries containing name/value pairs for each attribute passed as parameters:

>>> Foo.objects.all().values('user__id')
[{'user__id': 1}, {'user__id' 2}, {'user__id': 3}]

The ORM will then be able to optimize the SQL query to only return the required fields, instead of doing a "SELECT *".

Daniel
Hi Daniel,Your answer will help me in the future. Thanks!
Tiago
Will accessing user__id perform a JOIN? since it has to access the "id" attribute of the User table?
Jj
No - this is what I get out of django.db.connection.queries: SELECT "app_foo"."user_id" FROM "app_foo". the "__id" is superfluous, since the foreign key is only the ID to begin with. but specifying it seems more idiomatic to me, to make clear that you're getting an integer and not a user object.
Daniel
+2  A: 

Whenever you define a ForeignKey in Django, it automatically adds a FIELD_id field to your model.

For instance, if Foo has a FK to User with an attribute named "user", then you also have an attribute named user_id which contains the id of the related user.

l = [ f.user_id for f in foos ]

Calling .values() also adds performance if you select your attributes wisely

Jj