#9608 closed (fixed)
Broken model unicode methods can lead to bare exceptions
Reported by: | Karen Tracey | Owned by: | nobody |
---|---|---|---|
Component: | Core (Other) | Version: | 1.0 |
Severity: | Keywords: | ||
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Given this model registerd with the admin:
# -*- coding: utf-8 -*- from django.db import models class BrokenUnicodeMethod(models.Model): name = models.CharField(max_length=6) def __unicode__(self): return 'Názov: %s' % self.name
attempting to add one in the admin (with DEBUG set to True) generates a bare traceback:
Traceback (most recent call last): File "/home/kmt/django/trunk/django/core/servers/basehttp.py", line 278, in run self.result = application(self.environ, self.start_response) File "/home/kmt/django/trunk/django/core/servers/basehttp.py", line 635, in __call__ return self.application(environ, start_response) File "/home/kmt/django/trunk/django/core/handlers/wsgi.py", line 239, in __call__ response = self.get_response(request) File "/home/kmt/django/trunk/django/core/handlers/base.py", line 128, in get_response return self.handle_uncaught_exception(request, resolver, exc_info) File "/home/kmt/django/trunk/django/core/handlers/base.py", line 148, in handle_uncaught_exception return debug.technical_500_response(request, *exc_info) File "/home/kmt/django/trunk/django/views/debug.py", line 39, in technical_500_response html = reporter.get_traceback_html() File "/home/kmt/django/trunk/django/views/debug.py", line 97, in get_traceback_html 'exception_value': smart_unicode(self.exc_value, errors='replace'), File "/home/kmt/django/trunk/django/utils/encoding.py", line 35, in smart_unicode return force_unicode(s, encoding, strings_only, errors) File "/home/kmt/django/trunk/django/utils/encoding.py", line 70, in force_unicode raise DjangoUnicodeDecodeError(s, *e.args) DjangoUnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128). You passed in DjangoUnicodeDecodeError('ascii', 'N\xc3\xa1zov: ', 1, 2, 'ordinal not in range(128)') (<class 'django.utils.encoding.DjangoUnicodeDecodeError'>)
The original DjanoUnicodeDecodeError comes from the admin trying a force_unicode on the new object for the log message. That gets caught and get_traceback_html
attempts to calls smart_unicode
on the exception value, which ultimately calls the __str__
method for DjangoUnicodeDecodeError:
def __str__(self): original = UnicodeDecodeError.__str__(self) return '%s. You passed in %r (%s)' % (original, self.obj, type(self.obj))
self.obj
is the origin object where __unicode__
generated an exception. But the attempt to use its repr is going to call unicode on it again, since __repr__
for an model is (from django/db/models/base.py):
def __repr__(self): return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self)))
and we get another UnicodeDecodeException.
Of course the model's __unicode__
method is broken, returning non-ASCII data in a bytestring instead of a unicode object, but Django shouldn't obscure that error by generating an error itself trying to say that. Specifically I think the model __repr__
ought to guard against unicode(self)
generating an exception and substitute placeholder text if that happens, but I'm not entirely sure of that so I didn't just do it. Other opinions?
The original problem was reported in this thread: http://groups.google.com/group/django-users/browse_thread/thread/4209cc8f669f5e12
and involved a __unicode__
method that looked like this:
def __unicode__(self): return "%s %s" % (self.vrstva, self.nazov)
Here 'vrstva' is a foreign key, with a valid __unicode__
method that was returning non-ASCII data, converted to a utf-8 bytestring by the default Model __str__
method:
def __str__(self): if hasattr(self, '__unicode__'): return force_unicode(self).encode('utf-8') return '%s object' % self.__class__.__name__
Change History (3)
comment:1 by , 16 years ago
Component: | Uncategorized → Core framework |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 16 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
I wouldn't want to diguise this error too much, but you're right about bullet-proofing the debug page. Making repr() immune to the problem sounds like a good fix, since that will help with interactive debugging as well. Catching unicode encode errors and replacing it with something like "[Bad Unicode data]" would work for me.