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 [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---