I have taken a bit of time to rewrite part of the QuerySet code (including select_related). Please, no lectures about a QuerySet refactoring.
The changes force .filter() to take advantage of select_related.
Before: .filter(mykey__name='Hello') would give you results, but if you didn't do .select_related(depth=1) you would not have mykey in memory. After: it does :P
The changes also change select_related's args: MyModel.objects.filter(mykey__name="hello").select_related('mykey__author') will automatically join on mykey__author and keep it in memory.
The biggest thing this fixes is the SQL query optimization, previously it would have done two JOINs on mykey's table, even if the SQL engine optimized it, it's best to optimize it in the code.
This also letse you say MyModel.objects.all().select_related('mykey__author') which will hold both mykey, and mykey__author values in memory on the objects.
The depth argument still exists, so MyModel.objects.all().select_related('mykey', depth=1). The result of this query.. is nothing, because you implicitly set the fields to "mykey". If however, you said select_related('mykey__author', depth=1) it would not select on author, only on mykey, because that was specified.
If people are willing to discuss, or accept this, I will patch SVN with it. I will still most likely release the patch as I know a LOT of people want the "fields" selector in select_related().
> I have taken a bit of time to rewrite part of the QuerySet code > (including select_related). Please, no lectures about a QuerySet > refactoring.
> The changes force .filter() to take advantage of select_related.
> Before: .filter(mykey__name='Hello') would give you results, but if > you didn't do .select_related(depth=1) you would not have mykey in > memory. > After: it does :P
> The changes also change select_related's args: > MyModel.objects.filter(mykey__name="hello").select_related('mykey__author') > will automatically join on mykey__author and keep it in memory.
> The biggest thing this fixes is the SQL query optimization, previously > it would have done two JOINs on mykey's table, even if the SQL engine > optimized it, it's best to optimize it in the code.
> This also letse you say > MyModel.objects.all().select_related('mykey__author') which will hold > both mykey, and mykey__author values in memory on the objects.
> The depth argument still exists, so > MyModel.objects.all().select_related('mykey', depth=1). The result of > this query.. is nothing, because you implicitly set the fields to > "mykey". If however, you said select_related('mykey__author', depth=1) > it would not select on author, only on mykey, because that was > specified.
> If people are willing to discuss, or accept this, I will patch SVN > with it. I will still most likely release the patch as I know a LOT of > people want the "fields" selector in select_related().
> Seems I slipped in the diff. I have to actually apply the patch to at > least 2 different versions of Django with our current setup, can get > tedious :P
> *args should be *fields :)
;-)
Well, for the deeper levels, is there a way to express "follow myforeignkey__user recursively" and also "follow myforeignkey__user, but no deeper" without using the depth parameter (because you might want to follow to different depths in different foreign keys)?
Michael
-- noris network AG - Deutschherrnstraße 15-19 - D-90429 Nürnberg - Tel +49-911-9352-0 - Fax +49-911-9352-100 http://www.noris.de - The IT-Outsourcing Company
Vorstand: Ingo Kraupa (Vorsitzender), Joachim Astel, Hansjochen Klenk - Vorsitzender des Aufsichtsrats: Stefan Schnabel - AG Nürnberg HRB 17689
This was my best solution. I honestly wouldnt ever encourage anything where you dont specify which foreignkeys to follow. JOINs can get very slow when they expand beyond 2 or 3 tables, especially when table sizes increase.
On Aug 2, 2:28 am, Michael Radziej <m...@noris.de> wrote:
> > Seems I slipped in the diff. I have to actually apply the patch to at > > least 2 different versions of Django with our current setup, can get > > tedious :P
> > *args should be *fields :)
> ;-)
> Well, for the deeper levels, is there a way to express "follow > myforeignkey__user recursively" and also "follow myforeignkey__user, but no > deeper" without using the depth parameter (because you might want to follow > to different depths in different foreign keys)?
> Michael
> -- > noris network AG - Deutschherrnstraße 15-19 - D-90429 Nürnberg - > Tel +49-911-9352-0 - Fax +49-911-9352-100http://www.noris.de- The IT-Outsourcing Company
> Vorstand: Ingo Kraupa (Vorsitzender), Joachim Astel, Hansjochen Klenk - > Vorsitzender des Aufsichtsrats: Stefan Schnabel - AG Nürnberg HRB 17689
> This was my best solution. I honestly wouldnt ever encourage anything > where you dont specify which foreignkeys to follow. JOINs can get very > slow when they expand beyond 2 or 3 tables, especially when table > sizes increase.
Agreed ;-) I even think the max_depth argument should be removed, it doesn't really make sense.
I have something similar that is able to correctly generate outer joins for nullable foreign keys. It's currently only for my use since it's probably mysql only, and it can't correctly nest joins if you need an inner join to an outer join (hope this makes sense to you). It's also written for a different API (but I prefer your idea).
I've attached it for a quick look, are you interested in joining our efforts?
Michael
-- noris network AG - Deutschherrnstraße 15-19 - D-90429 Nürnberg - Tel +49-911-9352-0 - Fax +49-911-9352-100 http://www.noris.de - The IT-Outsourcing Company
Vorstand: Ingo Kraupa (Vorsitzender), Joachim Astel, Hansjochen Klenk - Vorsitzender des Aufsichtsrats: Stefan Schnabel - AG Nürnberg HRB 17689