mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
unicode: Fixed a number of problems where lazily translated objects were not
being converted back to unicode strings correctly. Fixed #4359 and #4361. git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5320 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
d72f630fdb
commit
b25f6e9526
@ -78,7 +78,7 @@ def result_headers(cl):
|
||||
# attribute "short_description". If that doesn't exist, fall back
|
||||
# to the method name. And __str__ and __unicode__ are special-cases.
|
||||
if field_name == '__unicode__':
|
||||
header = smart_unicode(lookup_opts.verbose_name)
|
||||
header = force_unicode(lookup_opts.verbose_name)
|
||||
elif field_name == '__str__':
|
||||
header = smart_str(lookup_opts.verbose_name)
|
||||
else:
|
||||
|
@ -12,7 +12,7 @@ from django.db.models.query import handle_legacy_orderlist, QuerySet
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||
from django.utils.html import escape
|
||||
from django.utils.text import capfirst, get_text_list
|
||||
from django.utils.encoding import smart_unicode, smart_str
|
||||
from django.utils.encoding import force_unicode, smart_str
|
||||
from django.utils.translation import ugettext as _
|
||||
import operator
|
||||
|
||||
@ -127,11 +127,11 @@ class AdminBoundField(object):
|
||||
if max([bool(f.errors()) for f in self.form_fields]):
|
||||
classes.append('error')
|
||||
if classes:
|
||||
self.cell_class_attribute = ' class="%s" ' % ' '.join(classes)
|
||||
self.cell_class_attribute = u' class="%s" ' % ' '.join(classes)
|
||||
self._repr_filled = False
|
||||
|
||||
if field.rel:
|
||||
self.related_url = '../../../%s/%s/' % (field.rel.to._meta.app_label, field.rel.to._meta.object_name.lower())
|
||||
self.related_url = u'../../../%s/%s/' % (field.rel.to._meta.app_label, field.rel.to._meta.object_name.lower())
|
||||
|
||||
def original_value(self):
|
||||
if self.original:
|
||||
@ -144,7 +144,7 @@ class AdminBoundField(object):
|
||||
if isinstance(self.field.rel, models.ManyToOneRel):
|
||||
self._display = getattr(self.original, self.field.name)
|
||||
elif isinstance(self.field.rel, models.ManyToManyRel):
|
||||
self._display = u", ".join([smart_unicode(obj) for obj in getattr(self.original, self.field.name).all()])
|
||||
self._display = u", ".join([force_unicode(obj) for obj in getattr(self.original, self.field.name).all()])
|
||||
return self._display
|
||||
|
||||
def __repr__(self):
|
||||
@ -255,7 +255,7 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
|
||||
if not errors:
|
||||
new_object = manipulator.save(new_data)
|
||||
pk_value = new_object._get_pk_val()
|
||||
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, smart_unicode(new_object), ADDITION)
|
||||
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, force_unicode(new_object), ADDITION)
|
||||
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_object}
|
||||
# Here, we distinguish between different save types by checking for
|
||||
# the presence of keys in request.POST.
|
||||
@ -268,7 +268,7 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
|
||||
if type(pk_value) is str: # Quote if string, so JavaScript doesn't think it's a variable.
|
||||
pk_value = '"%s"' % pk_value.replace('"', '\\"')
|
||||
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
|
||||
(pk_value, smart_unicode(new_object).replace('"', '\\"')))
|
||||
(pk_value, force_unicode(new_object).replace('"', '\\"')))
|
||||
elif "_addanother" in request.POST:
|
||||
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
|
||||
return HttpResponseRedirect(request.path)
|
||||
@ -342,7 +342,7 @@ def change_stage(request, app_label, model_name, object_id):
|
||||
change_message = ' '.join(change_message)
|
||||
if not change_message:
|
||||
change_message = _('No fields changed.')
|
||||
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, smart_unicode(new_object), CHANGE, change_message)
|
||||
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, force_unicode(new_object), CHANGE, change_message)
|
||||
|
||||
msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj': new_object}
|
||||
if "_continue" in request.POST:
|
||||
@ -431,10 +431,10 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
|
||||
if related.field.rel.edit_inline or not related.opts.admin:
|
||||
# Don't display link to edit, because it either has no
|
||||
# admin or is edited inline.
|
||||
nh(deleted_objects, current_depth, ['%s: %s' % (capfirst(related.opts.verbose_name), sub_obj), []])
|
||||
nh(deleted_objects, current_depth, [u'%s: %s' % (capfirst(related.opts.verbose_name), sub_obj), []])
|
||||
else:
|
||||
# Display a link to the admin page.
|
||||
nh(deleted_objects, current_depth, ['%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
|
||||
nh(deleted_objects, current_depth, [u'%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
|
||||
(capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(),
|
||||
sub_obj._get_pk_val(), sub_obj), []])
|
||||
_get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
|
||||
@ -445,10 +445,10 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
|
||||
if related.field.rel.edit_inline or not related.opts.admin:
|
||||
# Don't display link to edit, because it either has no
|
||||
# admin or is edited inline.
|
||||
nh(deleted_objects, current_depth, ['%s: %s' % (capfirst(related.opts.verbose_name), escape(sub_obj)), []])
|
||||
nh(deleted_objects, current_depth, [u'%s: %s' % (capfirst(related.opts.verbose_name), escape(sub_obj)), []])
|
||||
else:
|
||||
# Display a link to the admin page.
|
||||
nh(deleted_objects, current_depth, ['%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
|
||||
nh(deleted_objects, current_depth, [u'%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
|
||||
(capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(), sub_obj._get_pk_val(), escape(sub_obj)), []])
|
||||
_get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
|
||||
# If there were related objects, and the user doesn't have
|
||||
@ -481,12 +481,12 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
|
||||
# Display a link to the admin page.
|
||||
nh(deleted_objects, current_depth, [
|
||||
(_('One or more %(fieldname)s in %(name)s:') % {'fieldname': related.field.verbose_name, 'name':related.opts.verbose_name}) + \
|
||||
(' <a href="../../../../%s/%s/%s/">%s</a>' % \
|
||||
(u' <a href="../../../../%s/%s/%s/">%s</a>' % \
|
||||
(related.opts.app_label, related.opts.module_name, sub_obj._get_pk_val(), escape(sub_obj))), []])
|
||||
# If there were related objects, and the user doesn't have
|
||||
# permission to change them, add the missing perm to perms_needed.
|
||||
if related.opts.admin and has_related_objs:
|
||||
p = '%s.%s' % (related.opts.app_label, related.opts.get_change_permission())
|
||||
p = u'%s.%s' % (related.opts.app_label, related.opts.get_change_permission())
|
||||
if not user.has_perm(p):
|
||||
perms_needed.add(related.opts.verbose_name)
|
||||
|
||||
@ -503,14 +503,14 @@ def delete_stage(request, app_label, model_name, object_id):
|
||||
|
||||
# Populate deleted_objects, a data structure of all related objects that
|
||||
# will also be deleted.
|
||||
deleted_objects = ['%s: <a href="../../%s/">%s</a>' % (capfirst(opts.verbose_name), object_id, escape(obj)), []]
|
||||
deleted_objects = [u'%s: <a href="../../%s/">%s</a>' % (capfirst(opts.verbose_name), object_id, escape(obj)), []]
|
||||
perms_needed = sets.Set()
|
||||
_get_deleted_objects(deleted_objects, perms_needed, request.user, obj, opts, 1)
|
||||
|
||||
if request.POST: # The user has already confirmed the deletion.
|
||||
if perms_needed:
|
||||
raise PermissionDenied
|
||||
obj_display = smart_unicode(obj)
|
||||
obj_display = force_unicode(obj)
|
||||
obj.delete()
|
||||
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, object_id, obj_display, DELETION)
|
||||
request.user.message_set.create(message=_('The %(name)s "%(obj)s" was deleted successfully.') % {'name': opts.verbose_name, 'obj': obj_display})
|
||||
@ -600,7 +600,7 @@ class ChangeList(object):
|
||||
del p[k]
|
||||
elif v is not None:
|
||||
p[k] = v
|
||||
return '?' + '&'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
|
||||
return '?' + '&'.join([u'%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
|
||||
|
||||
def get_results(self, request):
|
||||
paginator = ObjectPaginator(self.query_set, self.lookup_opts.admin.list_per_page)
|
||||
|
@ -3,7 +3,7 @@ from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import backend, connection, models
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import datetime
|
||||
import urllib
|
||||
|
||||
@ -281,7 +281,7 @@ class AnonymousUser(object):
|
||||
pass
|
||||
|
||||
def __unicode__(self):
|
||||
return ugettext_lazy('AnonymousUser')
|
||||
return _('AnonymousUser')
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, self.__class__)
|
||||
|
@ -12,7 +12,7 @@ from django.db.models.loading import register_models, get_model
|
||||
from django.dispatch import dispatcher
|
||||
from django.utils.datastructures import SortedDict
|
||||
from django.utils.functional import curry
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.encoding import smart_str, force_unicode
|
||||
from django.conf import settings
|
||||
from itertools import izip
|
||||
import types
|
||||
@ -88,7 +88,7 @@ class Model(object):
|
||||
|
||||
def __str__(self):
|
||||
if hasattr(self, '__unicode__'):
|
||||
return unicode(self).encode('utf-8')
|
||||
return force_unicode(self).encode('utf-8')
|
||||
return '%s object' % self.__class__.__name__
|
||||
|
||||
def __eq__(self, other):
|
||||
@ -320,7 +320,7 @@ class Model(object):
|
||||
|
||||
def _get_FIELD_display(self, field):
|
||||
value = getattr(self, field.attname)
|
||||
return dict(field.choices).get(value, value)
|
||||
return force_unicode(dict(field.choices).get(value, value))
|
||||
|
||||
def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs):
|
||||
op = is_next and '>' or '<'
|
||||
|
@ -215,7 +215,7 @@ class AdminOptions(object):
|
||||
save_on_top=False, list_select_related=False, manager=None, list_per_page=100):
|
||||
self.fields = fields
|
||||
self.js = js or []
|
||||
self.list_display = list_display or ['__str__']
|
||||
self.list_display = list_display or ['__unicode__']
|
||||
self.list_display_links = list_display_links or []
|
||||
self.list_filter = list_filter or []
|
||||
self.date_hierarchy = date_hierarchy
|
||||
|
@ -58,9 +58,9 @@ import re
|
||||
from inspect import getargspec
|
||||
from django.conf import settings
|
||||
from django.template.context import Context, RequestContext, ContextPopException
|
||||
from django.utils.functional import curry
|
||||
from django.utils.functional import curry, Promise
|
||||
from django.utils.text import smart_split
|
||||
from django.utils.encoding import smart_unicode, smart_str
|
||||
from django.utils.encoding import smart_unicode, smart_str, force_unicode
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
__all__ = ('Template', 'Context', 'RequestContext', 'compile_string')
|
||||
@ -705,6 +705,8 @@ def resolve_variable(path, context):
|
||||
else:
|
||||
raise
|
||||
del bits[0]
|
||||
if isinstance(current, (basestring, Promise)):
|
||||
current = force_unicode(current)
|
||||
return current
|
||||
|
||||
class Node(object):
|
||||
|
@ -33,7 +33,7 @@ __test__ = {'API_TESTS':"""
|
||||
>>> s.gender
|
||||
'F'
|
||||
>>> a.get_gender_display()
|
||||
'Male'
|
||||
u'Male'
|
||||
>>> s.get_gender_display()
|
||||
'Female'
|
||||
u'Female'
|
||||
"""}
|
||||
|
@ -123,6 +123,9 @@ class ListFilterBadOne(models.Model):
|
||||
class Admin:
|
||||
list_filter = 'first_name'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
model_errors += """invalid_admin_options.listfilterbadone: "admin.list_filter", if given, must be set to a list or tuple.
|
||||
"""
|
||||
|
||||
@ -140,6 +143,9 @@ class ListFilterBadTwo(models.Model):
|
||||
class Admin:
|
||||
list_filter = ['first_name','last_name','full_name']
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
model_errors += """invalid_admin_options.listfilterbadtwo: "admin.list_filter" refers to 'last_name', which isn't a field.
|
||||
invalid_admin_options.listfilterbadtwo: "admin.list_filter" refers to 'full_name', which isn't a field.
|
||||
"""
|
||||
@ -152,6 +158,9 @@ class DateHierarchyBadOne(models.Model):
|
||||
class Admin:
|
||||
date_hierarchy = 'first_name'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
# TODO: Date Hierarchy needs to check if field is a date/datetime field.
|
||||
#model_errors += """invalid_admin_options.datehierarchybadone: "admin.date_hierarchy" refers to 'first_name', which isn't a date field or datetime field.
|
||||
#"""
|
||||
@ -164,6 +173,9 @@ class DateHierarchyBadTwo(models.Model):
|
||||
class Admin:
|
||||
date_hierarchy = 'nonexistent'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
model_errors += """invalid_admin_options.datehierarchybadtwo: "admin.date_hierarchy" refers to 'nonexistent', which isn't a field.
|
||||
"""
|
||||
|
||||
@ -175,6 +187,9 @@ class DateHierarchyGood(models.Model):
|
||||
class Admin:
|
||||
date_hierarchy = 'birth_day'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
class SearchFieldsBadOne(models.Model):
|
||||
"Test search_fields, must be a list or tuple."
|
||||
first_name = models.CharField(maxlength=30)
|
||||
@ -182,6 +197,9 @@ class SearchFieldsBadOne(models.Model):
|
||||
class Admin:
|
||||
search_fields = ('nonexistent')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
# TODO: Add search_fields validation
|
||||
#model_errors += """invalid_admin_options.seacrhfieldsbadone: "admin.search_fields", if given, must be set to a list or tuple.
|
||||
#"""
|
||||
@ -197,6 +215,9 @@ class SearchFieldsBadTwo(models.Model):
|
||||
class Admin:
|
||||
search_fields = ['first_name','last_name']
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
# TODO: Add search_fields validation
|
||||
#model_errors += """invalid_admin_options.seacrhfieldsbadone: "admin.search_fields" refers to 'last_name', which isn't a field.
|
||||
#"""
|
||||
@ -209,6 +230,8 @@ class SearchFieldsGood(models.Model):
|
||||
class Admin:
|
||||
search_fields = ['first_name','last_name']
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
class JsBadOne(models.Model):
|
||||
"Test js, must be a list or tuple"
|
||||
@ -217,6 +240,9 @@ class JsBadOne(models.Model):
|
||||
class Admin:
|
||||
js = 'test.js'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
# TODO: Add a js validator
|
||||
#model_errors += """invalid_admin_options.jsbadone: "admin.js", if given, must be set to a list or tuple.
|
||||
#"""
|
||||
@ -228,6 +254,9 @@ class SaveAsBad(models.Model):
|
||||
class Admin:
|
||||
save_as = 'not True or False'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
# TODO: Add a save_as validator.
|
||||
#model_errors += """invalid_admin_options.saveasbad: "admin.save_as", if given, must be set to True or False.
|
||||
#"""
|
||||
@ -239,6 +268,9 @@ class SaveOnTopBad(models.Model):
|
||||
class Admin:
|
||||
save_on_top = 'not True or False'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
# TODO: Add a save_on_top validator.
|
||||
#model_errors += """invalid_admin_options.saveontopbad: "admin.save_on_top", if given, must be set to True or False.
|
||||
#"""
|
||||
@ -250,6 +282,9 @@ class ListSelectRelatedBad(models.Model):
|
||||
class Admin:
|
||||
list_select_related = 'not True or False'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
# TODO: Add a list_select_related validator.
|
||||
#model_errors += """invalid_admin_options.listselectrelatebad: "admin.list_select_related", if given, must be set to True or False.
|
||||
#"""
|
||||
@ -261,6 +296,9 @@ class ListPerPageBad(models.Model):
|
||||
class Admin:
|
||||
list_per_page = 89.3
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
# TODO: Add a list_per_page validator.
|
||||
#model_errors += """invalid_admin_options.listperpagebad: "admin.list_per_page", if given, must be a positive integer.
|
||||
#"""
|
||||
@ -273,6 +311,9 @@ class FieldsBadOne(models.Model):
|
||||
class Admin:
|
||||
fields = 'not a tuple'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
# TODO: Add a fields validator.
|
||||
#model_errors += """invalid_admin_options.fieldsbadone: "admin.fields", if given, must be a tuple.
|
||||
#"""
|
||||
@ -285,6 +326,9 @@ class FieldsBadTwo(models.Model):
|
||||
class Admin:
|
||||
fields = ('Name', {'description': 'this fieldset needs fields'})
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
# TODO: Add a fields validator.
|
||||
#model_errors += """invalid_admin_options.fieldsbadtwo: "admin.fields" each fieldset must include a 'fields' dict.
|
||||
#"""
|
||||
@ -297,6 +341,9 @@ class FieldsBadThree(models.Model):
|
||||
class Admin:
|
||||
fields = ('Name', {'fields': ('first_name','last_name'),'badoption': 'verybadoption'})
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
# TODO: Add a fields validator.
|
||||
#model_errors += """invalid_admin_options.fieldsbadthree: "admin.fields" fieldset options must be either 'classes' or 'description'.
|
||||
#"""
|
||||
@ -313,6 +360,9 @@ class FieldsGood(models.Model):
|
||||
(None, {'fields': ('birth_day',),'description': 'enter your b-day'})
|
||||
)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
class OrderingBad(models.Model):
|
||||
"Test ordering, must be a field."
|
||||
first_name = models.CharField(maxlength=30)
|
||||
@ -321,6 +371,9 @@ class OrderingBad(models.Model):
|
||||
class Admin:
|
||||
ordering = 'nonexistent'
|
||||
|
||||
def __unicode__(self):
|
||||
return self.first_name
|
||||
|
||||
# TODO: Add a ordering validator.
|
||||
#model_errors += """invalid_admin_options.orderingbad: "admin.ordering" refers to 'nonexistent', which isn't a field.
|
||||
#"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user