Sunday, February 27, 2011

Re: Query Builder forgets annotations

On Sat, Feb 26, 2011 at 12:39 PM, Pascal Germroth <funkycoder@gmail.com> wrote:
It seems the query builder forgets annotations when dealing with joins:


Not in my experience.
 

I have this model with Postgresql, Django 1.3 alpha 1 (SVN rev. 15659):

I don't quite understand that Django rev spec. r15659 is quite recent (less than two days ago), but an SVN checkout should be reporting the version an 1.3 beta, not 1.3 alpha. What are you running exactly?
 

 class Corporation(Model):
   uuid = UuidField(primary_key=True)

 class Branch(Model):
   uuid = UuidField(primary_key=True)
   corporation = ForeignKey(Corporation, related_name='branches')


I don't know exactly what UuidField here is so for my test I change this to:

class Corporation(models.Model):
    uuid = models.CharField(max_length=14, primary_key=True)

    def __unicode__(self):
        return u'Corp %s with %d branches' % (self.uuid, self.branches.count())

class Branch(models.Model):
    uuid = models.CharField(max_length=14, primary_key=True)
    corporation = models.ForeignKey(Corporation, related_name='branches')



Now I want to retrieve the corporations ordered by the number of their
branches:
 Corporation.objects.annotate(x=Count('branches')).order_by('x')

Which fails with:
 FieldError: Cannot resolve keyword 'x' into field. Choices are:
branches, uuid in /django/db/models/sql/query.py in setup_joins, line 1236


Not for me:

python manage.py shell
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import django
>>> django.get_version()
u'1.3 beta 1 SVN-15659'
>>> from ttt.models import Corporation
>>> from django.db.models import Count
>>> Corporation.objects.annotate(x=Count('branches')).order_by('x')
[<Corporation: Corp c3 with 0 branches>, <Corporation: Corp c2 with 1 branches>, <Corporation: Corp c1 with 3 branches>]


This
 Corporation.objects.annotate(x=Count('branches'))
yields
 SELECT corporation.uuid, COUNT(branch.uuid) AS x FROM corporation LEFT
OUTER JOIN branch ON (corporation.uuid = branch.corporation_id) GROUP BY
corporation.uuid, corporation.uuid

and executing this query manually, with `ORDER BY x` added, gives me
what I want.

Is this a django bug, or by design?


In my test, the ORM query you show generates the above SQL plus the requested order by:

>>> from django.db import connection
>>> connection.queries[0]['sql']
'SELECT "ttt_corporation"."uuid", COUNT("ttt_branch"."uuid") AS "x" FROM "ttt_corporation" LEFT OUTER JOIN "ttt_branch" ON ("ttt_corporation"."uuid" = "ttt_branch"."corporation_id") GROUP BY "ttt_corporation"."uuid", "ttt_corporation"."uuid" ORDER BY "x" ASC LIMIT 21'

Something other than what you have shown (and I don't think it is the missing UuidField definition) is coming into play here to produce the results you are seeing. I have no idea what that is though.

Karen
--
http://tracey.org/kmt/

--
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+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

No comments:

Post a Comment