Works perfectly, thanks :)  Tested with a join 4 levels deep too and
it made just one query.

I use select_related elsewhere for more generic optimizations but it
hadn't occurred to me that django would need the hint once in
conjunction with an only() call.  Perhaps a patch to ensure that the
appropriate select_related call is made in conjunction with an only()
would make sense?

On Sep 27, 8:28 pm, Alasdair Nicol <alasd...@memset.com> wrote:
> Hi John,
>
> Use select_related [1] to tell Django to 'follow' the foreign key. Try
> the following:
>
> testmodels = 
> models.ATestModel.objects.all().select_related('other').only('other__name')
> print testmodels[0].other.name
>
> Regards,
> Alasdair
>
> [1]:https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-re...
>
> On 27/09/11 21:49, John wrote:
>
>
>
>
>
>
>
>
>
> > Hey,
>
> > I'm trying to improve the performance of a Django app, and noticed
> > that you can't seem to properly defer fields when making lookups with
> > joins.  To demonstrate, I set up a test project with the following
> > models:
>
> > class ATestModel(models.Model):
> >      other = models.ForeignKey('OtherModel')
>
> > class OtherModel(models.Model):
> >      name = models.CharField(max_length=32)
>
> > then, in the Django shell, I set up 10 'ATestModel's and two
> > 'OtherModel's properly linked up, and ran the following:
>
> >>>> from testmodule import models
> >>>> testmodels = models.ATestModel.objects.all().only('other__name')
> >>>> print testmodels[0].other.name
> > Test One
> >>>> from django.db import connection
> >>>> print '\n\n'.join([x['sql'] for x in connection.queries])
> > SELECT "testmodule_atestmodel"."id",
> > "testmodule_atestmodel"."other_id" FROM "testmodule_atestmodel" LIMIT
> > 1
>
> > SELECT "testmodule_othermodel"."id", "testmodule_othermodel"."name"
> > FROM "testmodule_othermodel" WHERE "testmodule_othermodel"."id" = 1
>
> > I also re-ran that without the 'only' call:
>
> >>>> testmodels = models.ATestModel.objects.all()
> >>>> print testmodels[0].other.name
> > Test One
> >>>> print '\n\n'.join([x['sql'] for x in connection.queries[2:]])
> > SELECT "testmodule_atestmodel"."id",
> > "testmodule_atestmodel"."other_id" FROM "testmodule_atestmodel" LIMIT
> > 1
>
> > SELECT "testmodule_othermodel"."id", "testmodule_othermodel"."name"
> > FROM "testmodule_othermodel" WHERE "testmodule_othermodel"."id" = 1
>
> > The 'only' call does nothing, and two queries are made when one would
> > have sufficed (SELECT testmodule_othermodel.name FROM
> > testmodule_atestmodel LEFT JOIN testmodule_othermodel ON
> > testmodule_atestmodel.id = testmodule_othermodule.id).  This raises a
> > huge performance penalty for highly normalized schemas and I would
> > even go so far as to say it in fact makes it impossible to optimize
> > queries with a decently normalized schema.
>
> > My apologies if someone has brought this up before - I was unable to
> > see anything about it in the django tickets or mailing lists.
>
> --
> Alasdair Nicol
> Developer, MEMSET
>
> mail: alasd...@memset.com
>   web:http://www.memset.com/
>
> Memset Ltd., registration number 4504980. 25 Frederick Sanger Road, 
> Guildford, Surrey, GU2 7YD, UK.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to