#8110 closed (fixed)
Admin interface: 'long' object has no attribute 'isdigit'
Reported by: | anonymous | Owned by: | nobody |
---|---|---|---|
Component: | contrib.admin | Version: | 1.0 |
Severity: | Keywords: | ||
Cc: | piranha@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Time and again there is a error in the admin interface.
We noiced that the error occures just when option Debug = false,
and by changing it to true everything function normaly.
Traceback (most recent call last): File "/opt/elec/python/django/core/handlers/base.py", line 87, in get_response response = callback(request, *callback_args, **callback_kwargs) File "/opt/elec/python/django/contrib/admin/sites.py", line 142, in root return self.index(request) File "/opt/elec/python/django/views/decorators/cache.py", line 44, in _wrapped_view_func response = view_func(request, *args, **kwargs) File "/opt/elec/python/django/contrib/admin/sites.py", line 331, in index context_instance=template.RequestContext(request) File "/opt/elec/python/django/shortcuts/__init__.py", line 18, in render_to_response return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs) File "/opt/elec/python/django/template/loader.py", line 107, in render_to_string return t.render(context_instance) File "/opt/elec/python/django/template/__init__.py", line 176, in render return self.nodelist.render(context) File "/opt/elec/python/django/template/__init__.py", line 751, in render bits.append(self.render_node(node, context)) File "/opt/elec/python/django/template/__init__.py", line 764, in render_node return node.render(context) File "/opt/elec/python/django/template/loader_tags.py", line 97, in render return compiled_parent.render(context) File "/opt/elec/python/django/template/__init__.py", line 176, in render return self.nodelist.render(context) File "/opt/elec/python/django/template/__init__.py", line 751, in render bits.append(self.render_node(node, context)) File "/opt/elec/python/django/template/__init__.py", line 764, in render_node return node.render(context) File "/opt/elec/python/django/template/loader_tags.py", line 97, in render return compiled_parent.render(context) File "/opt/elec/python/django/template/__init__.py", line 176, in render return self.nodelist.render(context) File "/opt/elec/python/django/template/__init__.py", line 751, in render bits.append(self.render_node(node, context)) File "/opt/elec/python/django/template/__init__.py", line 764, in render_node return node.render(context) File "/opt/elec/python/django/template/loader_tags.py", line 24, in render result = self.nodelist.render(context) File "/opt/elec/python/django/template/__init__.py", line 751, in render bits.append(self.render_node(node, context)) File "/opt/elec/python/django/template/__init__.py", line 764, in render_node return node.render(context) File "/opt/elec/python/django/contrib/admin/templatetags/log.py", line 17, in render if not self.user.isdigit(): AttributeError: 'long' object has no attribute 'isdigit'
Attachments (2)
Change History (32)
comment:1 by , 16 years ago
comment:2 by , 16 years ago
I can confirm that the error appears from time to time.
However, the site on which it appears for me is still using the old admin. Would be nice to know what the original poster is using.
comment:4 by , 16 years ago
milestone: | → 1.0 |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:5 by , 16 years ago
Hmmm, this is quite difficult to debug. Can you please provide a test case or any code that reproduces the error?
I've never seen that error before, and at first glance it is hard to know what's causing it...
comment:6 by , 16 years ago
Resolution: | → worksforme |
---|---|
Status: | new → closed |
I can't reproduce this, either. We'll need more information -- your model, ModelAdmin
, etc. Marking worksforme; feel free to reopen if you can provide more information.
comment:7 by , 16 years ago
I updated the site where I got the error to newforms admin. Since the update, the error never occurred anymore, but it occurred very rarely nonetheless. I have no idea how to reproduce or why it still occurred for anonymous in his newforms admin.
by , 16 years ago
Attachment: | isdigitpatch.diff added |
---|
Since isdigit only works with strings we make it a string
follow-up: 10 comment:9 by , 16 years ago
Has patch: | set |
---|---|
Resolution: | worksforme |
Status: | closed → reopened |
Version: | SVN → 1.0 |
I don't know what causes the error, somehow self.user
can be long
sometimes. If I continuously refresh my admin page the error appears frequently now. The patch fixes it.
comment:10 by , 16 years ago
Replying to julianb:
I don't know what causes the error, somehow
self.user
can belong
sometimes. If I continuously refresh my admin page the error appears frequently now. The patch fixes it.
It would be good to understand how it comes about that sometimes self.user
is a long
. Looking at the code, one way would be if render
was called more than once for the same AdminLogNode
, since render itself rebinds self.user
from the user
variable name to the identified user's ID. I'm going to attach a patch that avoids doing that. Could you try running with it and seeing if it also prevents the error? If so, then the next question will by why is render
being called multiple times for the same AdminLogNode
? I thought that would only happen if the template tag (get_admin_log
in this case) was placed inside a loop in the template. It's not in a loop in the admin/index.html file. Have you customized this file or do you have another template that uses get_admin_log
in a loop? (I am unable to recreate the error myself by refreshing the admin page to the limits of my patience.)
by , 16 years ago
Allow for render being called more than once for an AdminLogNode
comment:11 by , 16 years ago
Your patch works. No errors while frequently reloading. (Btw, it seems to always enter the if condition, otherwise user_id would not be set, or maybe that's what you wanted to check.)
I have not customized anything so that the tag is in a loop...
I'm also getting the error on two different sites on different servers. One running mod_python and the other mod_wsgi.
comment:12 by , 16 years ago
Hmm, OK. So it looks like render is getting called multiple times for the same AdminLogNode
. I don't understand why that's happening, and can't recreate it (previously I had tried under the development server, now I have tried under mod_wsgi as well). I don't suppose you recall anything you changed in your configuration around 9/3 that could be relevant? Are you, like the original reporter, also running with debug off?
(I expected it was always entering the if condition, because the only use of that templatetag that I can find within Django passes in a variable name, not a user number. It seems to have been written to allow more options on calling it than are currently exercised by Django code.)
comment:13 by , 16 years ago
Another report, also noted to happen only with debug turned off: http://groups.google.com/group/django-users/browse_thread/thread/f335b27a221b6720
comment:14 by , 16 years ago
May be someone apply this patch to trunk and branch 1.0.x? This bug is really annoing and second patch really solve problem!
comment:15 by , 16 years ago
The problem with just applying the existing patch is it essentially hides a problem we don't yet understand the root cause of. I haven't been able to recreate the problem -- if you are seeing this regularly could you provide any feedback on your configuration including web server, middleware, caching setup, etc. that might help us figure out what is at the root of the problem? In the meantime the patch in the ticket can also be used by anyone experiencing the problem as a stopgap to avoid the error. But we'd like to better understand what is going on here before just patching over the error in the code base.
comment:16 by , 16 years ago
So, if it really can help. I'm install byteflow blog engine (http://byteflow.su/) on linux via fastcgi. webserver nginx. fastcgi via sockets. Django from trunk (today).
Some time later, I'm try to debug it.
comment:17 by , 16 years ago
I too have installed byteflow and am experiencing the same problem. I'm on Apache/mod_python sitting behind an nginx reverse proxy. Django 9084. I'm using SQLite.
I'm not getting this error on manage.py runserver.
follow-up: 19 comment:18 by , 16 years ago
To the people reorting this: Is it possible these conditions are being met in the cases you see the reported error?:
- Django is being executed in multiple threads (that would be Apache worker MPM + mod_python, or mod_wsgi in daemon mode)
- The admin app is being used at the same time by another user
follow-up: 20 comment:19 by , 16 years ago
Replying to ramiro:
To the people reorting this: Is it possible these conditions are being met in the cases you see the reported error?:
- Django is being executed in multiple threads (that would be Apache worker MPM + mod_python, or mod_wsgi in daemon mode)
No, I'm using preforked fastcgi flup server over WSGI.
- The admin app is being used at the same time by another user
No, im my installation Django has only one staff user.
But sometimes it happens when very fast refresh admin page.
comment:20 by , 16 years ago
Replying to oxyum:
Replying to ramiro:
To the people reorting this: Is it possible these conditions are being met in the cases you see the reported error?:
I can confirm this bug with byteflow and lighttpd 1.4.20. Django runs as fastcgi process with the following startup:
python manage.py runfcgi host=127.0.0.1 port=8888
Lighty has been configured like this:
fastcgi.server = ( "/byteflow.fcgi" => ( "main" => ( "min-procs" => 1, "max-procs" => 1, "host" => "127.0.0.1", "port" => 8888, #"socket" => "/usr/src/byteflow/socket" + var.PID, "check-local" => "disable", #"bin-path" => "/usr/src/byteflow/byteflow.fcgi" ) ) )
The wsgi environment shows this(copy from traceback mail):
<WSGIRequest GET:<QueryDict: {}>, POST:<QueryDict: {}>, COOKIES:{'sessionid': '6a0863baf921667e81217b534fd5c02b'}, META:{'DOCUMENT_ROOT': '/var/www/novh/', 'GATEWAY_INTERFACE': 'CGI/1.1', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_ACCEPT_CHARSET': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'HTTP_ACCEPT_ENCODING': 'gzip,deflate', 'HTTP_ACCEPT_LANGUAGE': 'en-us,en;q=0.5', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_COOKIE': 'sessionid=6a0863baf921667e81217b534fd5c02b', 'HTTP_HOST': 'blog.noordsee.de', 'HTTP_IF_MODIFIED_SINCE': 'Tue, 14 Oct 2008 18:15:38 GMT', 'HTTP_IF_NONE_MATCH': '"de6ded5f6a2828356f158f21599e28d9"', 'HTTP_KEEP_ALIVE': '300', 'HTTP_REFERER': 'http://xxxxxxxxxxxxxxxx/admin/blog/post/', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16', 'PATH_INFO': u'/admin/', 'PATH_TRANSLATED': '/var/www/novh//admin/', 'QUERY_STRING': '', 'REDIRECT_STATUS': '200', 'REDIRECT_URI': '/byteflow.fcgi/admin/', 'REMOTE_ADDR': '84.141.xxxxx.xxxx', 'REMOTE_PORT': '44745', 'REQUEST_METHOD': 'GET', 'REQUEST_URI': '/admin/', 'SCRIPT_FILENAME': '/var/www/novh/byteflow.fcgi', 'SCRIPT_NAME': u'', 'SERVER_ADDR': '85.214.xxxx.xxxxx', 'SERVER_NAME': 'xxxxxxxxxxxxx.de', 'SERVER_PORT': '80', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'lighttpd/1.4.20', 'wsgi.errors': <flup.server.fcgi_base.TeeOutputStream object at 0xb63266cc>, 'wsgi.input': <flup.server.fcgi_base.InputStream object at 0xb64a2c2c>, 'wsgi.multiprocess': True, 'wsgi.multithread': False, 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.version': (1, 0)}>
Last traceback call shows:
Original Traceback (most recent call last): File "/usr/local/lib/python2.5/site-packages/django/template/debug.py", line 71, in render_node result = node.render(context) File "/usr/local/lib/python2.5/site-packages/django/contrib/admin/templatetags/log.py", line 17, in render if not self.user.isdigit(): AttributeError: 'int' object has no attribute 'isdigit'
I am using the current 1.0 release (no trunk or 1.0.x branch) as Django installation. Lighty, python 2.5 and flup are compiled from current sourcecode releases.
If you set min and max processes on lighty to one you can get error 500 real fast switching from byteflows blog (edit some blog) to "home". Do this a few times and each time you call "/admin" you get error 500. This is only happening if the app runs in Debug=False mode. The blog runs on a VServer Virtuozzo system with (while for testing) SQLite3 as db backend.
Hope this helps!
comment:21 by , 16 years ago
I did today evening some debugging and found a bugfix / workaround for this behaviour.
Original file: django/contrib/admin/templatetags/log.py
def render(self, context): if self.user is None: context[self.varname] = LogEntry.objects.all().select_related()[:self.limit] else: if not self.user.isdigit(): self.user = context[self.user].id context[self.varname] = LogEntry.objects.filter(user__id__exact=self.user).select_related()[:self.limit] return ''
Look at the line "if not self.user.isdigit()". We assume that self.user must be an unicode string containing a digit value. If this is not the case we get the current user id from the context dictionary and save it as self.user. And now here it happends that we get the id which is an integer value and no string. So we ovwerwrite the current string with an integer. The next time the render method is called we try to call isdigit() on an integer object which crashes the admin interface (error 500). What I did to fix this is that I put str(..) around the context[self.user].id. So I make sure that self.user is a string, however containing an integer values so isdigit() will become true.
Fixed render method looks like:
def render(self, context): if self.user is None: context[self.varname] = LogEntry.objects.all().select_related()[:self.limit] else: if not self.user.isdigit(): self.user = str(context[self.user].id) context[self.varname] = LogEntry.objects.filter(user__id__exact=self.user).select_related()[:self.limit] return ''
follow-ups: 23 24 comment:22 by , 16 years ago
Thanks for the info. We already know how to prevent the error from occurring by either the approach you mention or just avoiding updating self.user inside render (see the patches already on the ticket). The reason neither has been applied to the code base is we'd really like to understand WHY render is being called more than once for this template tag. The template tag isn't in a loop or anything, so it is not clear why render() is being called multiple times for the same node. That's the mystery we'd like to understand before checking in a fix.
I am confused by your traceback included above. The one that starts "Original traceback" and starts with "django/template/debug.py", line 71,"...yet this bug you and everyone else reports only occurs with DEBUG set to False. There is also no mention of django/template/debug.py in the original posted traceback, nor any indication that there are multiple exceptions raised...so all in all I find that traceback info confusing.
comment:23 by , 16 years ago
Replying to kmtracey:
I am confused by your traceback included above. The one that starts "Original traceback" and starts with "django/template/debug.py", line 71,"...yet this bug you and everyone else reports only occurs with DEBUG set to False. There is also no mention of django/template/debug.py in the original posted traceback, nor any indication that there are multiple exceptions raised...so all in all I find that traceback info confusing.
To get my traceback I did uncomment the ADMIN settings variable in settings_local.py (from the byteflow installation). Thus I got the error 500 traceback mailed. The complete traceback reads (I have slighty formatted the output because c&p from my webclient did not copy carridge returns):
Traceback (most recent call last): File "/usr/local/lib/python2.5/site-packages/django/core/handlers/base.py", line 86, in get_response response = callback(request, *callback_args, **callback_kwargs) File "/usr/local/lib/python2.5/site-packages/django/contrib/admin/sites.py", line 145, in root return self.index(request) File "/usr/local/lib/python2.5/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func response = view_func(request, *args, **kwargs) File "/usr/local/lib/python2.5/site-packages/django/contrib/admin/sites.py", line 319, in index context_instance=template.RequestContext(request) File "/usr/local/lib/python2.5/site-packages/django/shortcuts/__init__.py", line 18, in render_to_response return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs) File "/usr/local/lib/python2.5/site-packages/django/template/loader.py", line 107, in render_to_string return t.render(context_instance) File "/usr/local/lib/python2.5/site-packages/django/template/__init__.py", line 176, in render return self.nodelist.render(context) File "/usr/local/lib/python2.5/site-packages/django/template/__init__.py", line 768, in render bits.append(self.render_node(node, context)) File "/usr/local/lib/python2.5/site-packages/django/template/debug.py", line 71, in render_node result = node.render(context) File "/usr/local/lib/python2.5/site-packages/django/template/loader_tags.py", line 97, in render return compiled_parent.render(context) File "/usr/local/lib/python2.5/site-packages/django/template/__init__.py", line 176, in render return self.nodelist.render(context) File "/usr/local/lib/python2.5/site-packages/django/template/__init__.py", line 768, in render bits.append(self.render_node(node, context)) File "/usr/local/lib/python2.5/site-packages/django/template/debug.py", line 71, in render_node result = node.render(context) File "/usr/local/lib/python2.5/site-packages/django/template/loader_tags.py", line 97, in render return compiled_parent.render(context) File "/usr/local/lib/python2.5/site-packages/django/template/__init__.py", line 176, in render return self.nodelist.render(context) File "/usr/local/lib/python2.5/site-packages/django/template/__init__.py", line 768, in render bits.append(self.render_node(node, context)) File "/usr/local/lib/python2.5/site-packages/django/template/debug.py", line 71, in render_node result = node.render(context) File "/usr/local/lib/python2.5/site-packages/django/template/loader_tags.py", line 24, in render result = self.nodelist.render(context) File "/usr/local/lib/python2.5/site-packages/django/template/__init__.py", line 768, in render bits.append(self.render_node(node, context)) File "/usr/local/lib/python2.5/site-packages/django/template/debug.py", line 81, in render_node raise wrapped TemplateSyntaxError: Caught an exception while rendering: 'int' object has no attribute 'isdigit' Original Traceback (most recent call last): File "/usr/local/lib/python2.5/site-packages/django/template/debug.py", line 71, in render_node result = node.render(context) File "/usr/local/lib/python2.5/site-packages/django/contrib/admin/templatetags/log.py", line 17, in render if not self.user.isdigit(): AttributeError: 'int' object has no attribute 'isdigit'
I know that casting from int to string is just a workaround and there must be a bug somewhere in the template stuff or otherwise.
comment:24 by , 16 years ago
Replying to kmtracey:
I am confused by your traceback included above. The one that starts "Original traceback" and starts with "django/template/debug.py", line 71,"...yet this bug you and everyone else reports only occurs with DEBUG set to False. There is also no mention of django/template/debug.py in the original posted traceback, nor any indication that there are multiple exceptions raised...so all in all I find that traceback info confusing.
That's small bug in byteflow default configuration. When we set DEBUG to False, DEBUG_TEMPLATES doesn't set to False. But I'm trying set DEBUG_TEMPLATES to False - it's doesn't matter.
comment:25 by , 16 years ago
OK, has anyone hit this WITHOUT having byteflow installed? Because after looking into byteflow I understand why it happens there: byteflow replaces Django's django.template.loader.get_template with its own cached_get_template which re-uses compiled templates:
TEMPLATE_CACHE = {} def cached_get_template(template_name): global TEMPLATE_CACHE t = TEMPLATE_CACHE.get(template_name, None) if not t or settings.DEBUG: source, origin = loader.find_template_source(template_name) t = loader.get_template_from_string(source, origin, template_name) TEMPLATE_CACHE[template_name] = t return t
That code also explains why this has only been observed with DEBUG set to False.
So, there is no mysterious re-use of compiled templates within Django itself, it's being done by the app. Assuming that's a legit thing for an app to do (?) the simple fix of avoiding changing self within render fixes it.
(Actually it strikes me as not a very legit thing to be doing because if multiple apps do what byteflow does:
from django import template from lib.template_loaders import cached_get_template template.loader.get_template = cached_get_template
the last one "wins" and the custom code of the others gets ignored. But there it is doing it, and the result is the admin interface generates a 500 error, which is ugly. Also if/when some form of "supported" template caching does get implemented, that would also run into trouble here. So I do think it has exposed a real bug in the render() function that we need to fix, despite not particularly liking what byteflow has done here. And I wonder how many other template tags may have similar issues with re-use of compiled versions.)
comment:26 by , 16 years ago
I run several Django sites and have *only* hit this bug on my Byteflow blog.
comment:27 by , 16 years ago
Yeah, this is a bug in the admin template tag which is notable when caching templates. The patch in #9154 fixes it (but really, it should be a separate ticket). There are also other issues around things like the cycle tag which store state on the node rather than the context.
comment:28 by , 16 years ago
Cc: | added |
---|
despite not particularly liking what byteflow has done here.
Yeah, it's not that nice, but redoing cached_get_template to use original loader.get_template doesn't help there. Is there any ideas what I can do except disabling caching (though I can go this way because anyway I'll add real caching in - probably near - future).
comment:29 by , 16 years ago
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
Can you post more information about your model and ModelAdmin?