I'm having a somewhat odd error occurring when I try to use
select_related() and annotate() in the same queryset.

The application I'm working on is a blog-type app where posts can be a
variety of types--article, book review, film review, etc.  I use multi-
table inheritance with a single base class, Node, and then each post
type with its own subclass, e.g. Article, BookReview, etc.  Each Node
has an FK relationship with an Archetype, which essentially just
contains a string saying whether the Node references an Article,
BookReview, or whatever.  Each Node also has an FK relationship with a
Section (used for grouping) and with several Comments.

Most of my views do some relatively simple queries and then pass a
queryset of Nodes to a base template, which then iterates over the
queryset and calls a custom template tag in each iteration to
determine what kind of node it is and render it.

In the view I'm currently working on, I use the
list_detail.object_list generic view with a wrapper around it.  In
order to speed things up, I added select_related() to my queryset,
like so:

Node.objects.select_related().filter(section__keyword=sect,
published=True).order_by('-created')

This worked pretty well, reducing the number of times the DB is hit in
the template significantly.

Now, something else I do in the template is display the number of
Comments associated with each Node.  That causes a couple of extra DB
hits per template iteration.  So I thought that using the annotate()
function would work nicely.  Like so:

Node.objects.select_related().filter(section__keyword=sect,
published=True).order_by('-created').annotate(comment_count=Count
('comment'))

Except, when I do that, something gets all messed up with the
resulting queryset.  Instances in the queryset have data in the wrong
fields.  This becomes apparent when I try to use my custom template
tag:

def render_node(node, user):
  template_name = node.archetype.classname.lower() + '_detail.html'
  edit = False
  if user.is_authenticated():
    if user.is_superuser or user.groups.filter
(name=node.section.keyword).count():
      edit = True
  return render_to_string(template_name, {'node': node, 'user': user,
'edit': edit})

This throws an exception, saying that "'long' object has no attribute
'lower'."  When I put in some diagnostic code to print
node.archetype.classname to the console, it comes out as a number,
which makes no sense.  Then when I tried printing node.comment_count,
it returns "Article," which is what should be returned by
node.archetype.classname.

If I remove select_related(), it works like I expect it should, except
that now the db is hit a bunch of extra times each time through the
loop.  If I remove annotate(), it also works.

Has anyone else seen behavior like this?

For reference, I am using r9781.
--~--~---------~--~----~------------~-------~--~----~
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