Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django QuerySet access foreign key field directly, without forcing a join

Suppose you have a model Entry, with a field "author" pointing to another model Author. Suppose this field can be null.

If I run the following QuerySet:

Entry.objects.filter(author=X)

Where X is some value. Suppose in MySQL I have setup a compound index on Entry for some other column and author_id, ideally I'd like the SQL to just use "author_id" on the Entry model, so that it can use the compound index.

It turns out that Entry.objects.filter(author=5) would work, no join is done. But, if I say author=None, Django does a join with Author, then add to the Where clause Author.id IS NULL. So in this case, it can't use the compound index.

Is there a way to tell Django to just check the pk, and not follow the link?

The only way I know is to add an additional .extra(where=['author_id IS NULL']) to the QuerySet, but I was hoping some magic in .filter() would work.

Thanks.

(Sorry I was not clearer earlier about this, and thanks for the answers from lazerscience and Josh).

like image 918
OverClocked Avatar asked Nov 15 '10 21:11

OverClocked


3 Answers

Does this not work as expected?

Entry.objects.filter(author=X.id)

You can either use a model or the model id in a foreign key filter. I can't check right yet if this executes a separate query, though I'd really hope it wouldn't.

like image 178
Josh Smeaton Avatar answered Nov 26 '22 17:11

Josh Smeaton


If do as you described and do not use select_related() Django will not perform any join at all - no matter if you filter for the primary key of the related object or the related itself (which doesn't make any difference).

You can try:

print Entry.objects.(author=X).query
like image 43
Bernhard Vallant Avatar answered Nov 26 '22 18:11

Bernhard Vallant


Assuming that the foreign key to Author has the name author_id, (if you didn't specify the name of the foreign key column for ForeignKey field, it should be NAME_id, if you specified the name, then check the model definition / your database schema),

Entry.objects.filter(author_id=value)

should work.

like image 44
Jeeyoung Kim Avatar answered Nov 26 '22 17:11

Jeeyoung Kim