Code

Opened 8 years ago

Closed 7 years ago

#2351 closed defect (fixed)

MySQL syntax error on object.all().count(), when called from template

Reported by: gumuz Owned by: adrian
Component: Database layer (models, ORM) Version:
Severity: normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: yes Patch needs improvement: no
Easy pickings: UI/UX:

Description

I have a blogpost model which is referenced by a Comment class. Thus, the Blogpost model has a comment_set attribute.

I gave the Blogpost model a method like this:

def comments(self):
    return self.comment_set.all()

When i access it from the shell and use the .count() method on the QuerySet, everything is fine:

>>> from devlog.weblog.models import Post
>>> p = Post.objects.all()[4]
>>> p.comments()
[<Comment: gumuz - 2006-07-12 07:10:30>, <Comment: gumuz - 2006-07-12 07:09:56>]
>>> p.comments().count()
2L

When i do the same from my template:

{{ object.comments.count }}

I get the following error:

Exception Type:  	ProgrammingError
Exception Value: 	(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'count,1' at line 1")
Exception Location: 	/usr/lib/python2.4/site-packages/MySQLdb/connections.py in defaulterrorhandler, line 33

The length-filter works fine though:

{{ object.comments|length }}

Attachments (3)

diff_fix_queryset_getitem.txt (756 bytes) - added by marcin@… 7 years ago.
backtrace_short.txt (1.4 KB) - added by marcin@… 7 years ago.
backtrace_detailed.txt (12.9 KB) - added by marcin@… 7 years ago.

Download all attachments as: .zip

Change History (14)

comment:1 Changed 8 years ago by racter@…

this error only happens for me when nesting -- ie if i try:

{% for object in category.object_set.all %}
{{ object.subobject_set.count }}
{% endfor %}

i get the same error.

comment:2 Changed 7 years ago by Jonas

I get the same error. count fails from template but |length works fine.

comment:3 Changed 7 years ago by Michael Radziej <mir@…>

Please, send the full bracktrace.

Changed 7 years ago by marcin@…

comment:4 Changed 7 years ago by marcin@…

  • Has patch set

I just ran into the same problem with Postgresql.

The cause is a bug in QuerySet.getitem: it assumes that the parameter it gets is either a slice or an integer, but does not really check the latter. When you put {{ somequeryset.qwe }} in your template and template.resolve_variable tries to resolve it using a dictionary lookup, QuerySet.getitem treats qwe like an integer index, which results in queries ending with "limit 1 offset qwe".

The attached patch fixes the problem.

comment:5 Changed 7 years ago by mir@…

It would be rather nice if someone posts the full backtrace. I personally refuse to triage a bug report without the full information, and it's rather tedious to reconstruct the problem when you're dealing with a lot of tickets.

Changed 7 years ago by marcin@…

Changed 7 years ago by marcin@…

comment:6 Changed 7 years ago by marcin@…

mir: here you are. Note the resulting SQL query at the end.

All the interesting parts of code:

models.py:

    class Article(models.Model):
        text = models.TextField()

urls.py:

    urlpatterns = patterns('',
        (r'^$', 'django.views.generic.simple.direct_to_template',
         {'extra_context': {'object_list': Article.objects.all()},
          'template': 'index.html'}),
    )

index.html:

{{ object_list.count }}

I tried to attach the detailed backtrace in HTML, but Akismet said it was spam.

comment:7 Changed 7 years ago by SmileyChris

  • Needs tests set
  • Triage Stage changed from Unreviewed to Accepted

I'll accept. Probably could do with some tests showing the failure.

comment:8 Changed 7 years ago by Noah Slater <nslater@…>

I can confirm identical behaviour.

comment:9 Changed 7 years ago by ubernostrum

#2945 was a duplicate of this one.

comment:10 Changed 7 years ago by ubernostrum

And for the record, #2945 has a full traceback of this bug. And I've seen it happen on SQLite as well.

comment:11 Changed 7 years ago by mtredinnick

  • Resolution set to fixed
  • Status changed from new to closed

(In [4772]) Fixed #2351 -- Fixed problem with using ".count" attribute of QuerySets in
templates.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.