Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

unicode: Adjusted the admin interface to handle unicode strings. May …

…still need

some tweaking, but the bulk of it should be correct. Fixed #4266.


git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5200 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 1026402499840f980e6a9f0c4cd9e92962ba1b10 1 parent 7c45aad
@malcolmt malcolmt authored
View
11 django/contrib/admin/filterspecs.py
@@ -7,6 +7,7 @@
"""
from django.db import models
+from django.utils.encoding import smart_unicode
import datetime
class FilterSpec(object):
@@ -37,10 +38,10 @@ def title(self):
def output(self, cl):
t = []
if self.has_output():
- t.append(_('<h3>By %s:</h3>\n<ul>\n') % self.title())
+ t.append(_(u'<h3>By %s:</h3>\n<ul>\n') % self.title())
for choice in self.choices(cl):
- t.append('<li%s><a href="%s">%s</a></li>\n' % \
+ t.append(u'<li%s><a href="%s">%s</a></li>\n' % \
((choice['selected'] and ' class="selected"' or ''),
choice['query_string'] ,
choice['display']))
@@ -70,7 +71,7 @@ def choices(self, cl):
'display': _('All')}
for val in self.lookup_choices:
pk_val = getattr(val, self.field.rel.to._meta.pk.attname)
- yield {'selected': self.lookup_val == str(pk_val),
+ yield {'selected': self.lookup_val == smart_unicode(pk_val),
'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}),
'display': val}
@@ -87,7 +88,7 @@ def choices(self, cl):
'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
'display': _('All')}
for k, v in self.field.choices:
- yield {'selected': str(k) == self.lookup_val,
+ yield {'selected': smart_unicode(k) == self.lookup_val,
'query_string': cl.get_query_string({self.lookup_kwarg: k}),
'display': v}
@@ -168,7 +169,7 @@ def choices(self, cl):
'query_string': cl.get_query_string({}, [self.field.name]),
'display': _('All')}
for val in self.lookup_choices:
- val = str(val[self.field.name])
+ val = smart_unicode(val[self.field.name])
yield {'selected': self.lookup_val == val,
'query_string': cl.get_query_string({self.field.name: val}),
'display': val}
View
4 django/contrib/admin/models.py
@@ -28,7 +28,7 @@ class Meta:
ordering = ('-action_time',)
def __repr__(self):
- return str(self.action_time)
+ return smart_unicode(self.action_time)
def is_addition(self):
return self.action_flag == ADDITION
@@ -48,4 +48,4 @@ def get_admin_url(self):
Returns the admin URL to edit the object represented by this log entry.
This is relative to the Django admin index page.
"""
- return "%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, self.object_id)
+ return u"%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, self.object_id)
View
31 django/contrib/admin/templatetags/admin_list.py
@@ -7,6 +7,7 @@
from django.utils.html import escape
from django.utils.text import capfirst
from django.utils.translation import get_date_formats, get_partial_date_formats
+from django.utils.encoding import smart_unicode, smart_str
from django.template import Library
import datetime
@@ -16,11 +17,11 @@
def paginator_number(cl,i):
if i == DOT:
- return '... '
+ return u'... '
elif i == cl.page_num:
- return '<span class="this-page">%d</span> ' % (i+1)
+ return u'<span class="this-page">%d</span> ' % (i+1)
else:
- return '<a href="%s"%s>%d</a> ' % (cl.get_query_string({PAGE_VAR: i}), (i == cl.paginator.pages-1 and ' class="end"' or ''), i+1)
+ return u'<a href="%s"%s>%d</a> ' % (cl.get_query_string({PAGE_VAR: i}), (i == cl.paginator.pages-1 and ' class="end"' or ''), i+1)
paginator_number = register.simple_tag(paginator_number)
def pagination(cl):
@@ -74,10 +75,12 @@ def result_headers(cl):
f = lookup_opts.get_field(field_name)
except models.FieldDoesNotExist:
# For non-field list_display values, check for the function
- # attribute "short_description". If that doesn't exist, fall
- # back to the method name. And __str__ is a special-case.
- if field_name == '__str__':
- header = lookup_opts.verbose_name
+ # 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)
+ elif field_name == '__str__':
+ header = smart_str(lookup_opts.verbose_name)
else:
attr = getattr(cl.model, field_name) # Let AttributeErrors propagate.
try:
@@ -112,7 +115,7 @@ def result_headers(cl):
def _boolean_icon(field_val):
BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'}
- return '<img src="%simg/admin/icon-%s.gif" alt="%s" />' % (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)
+ return u'<img src="%simg/admin/icon-%s.gif" alt="%s" />' % (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)
def items_for_result(cl, result):
first = True
@@ -134,7 +137,7 @@ def items_for_result(cl, result):
allow_tags = True
result_repr = _boolean_icon(attr)
else:
- result_repr = str(attr)
+ result_repr = smart_unicode(attr)
except (AttributeError, ObjectDoesNotExist):
result_repr = EMPTY_CHANGELIST_VALUE
else:
@@ -177,19 +180,19 @@ def items_for_result(cl, result):
elif f.choices:
result_repr = dict(f.choices).get(field_val, EMPTY_CHANGELIST_VALUE)
else:
- result_repr = escape(str(field_val))
+ result_repr = escape(field_val)
if result_repr == '':
result_repr = '&nbsp;'
# If list_display_links not defined, add the link tag to the first field
- if (first and not cl.lookup_opts.admin.list_display_links) or field_name in cl.lookup_opts.admin.list_display_links:
+ if (first and not cl.lookup_opts.admin.list_display_links) or field_name in cl.lookup_opts.admin.list_display_links:
table_tag = {True:'th', False:'td'}[first]
first = False
url = cl.url_for_result(result)
- result_id = str(getattr(result, pk)) # str() is needed in case of 23L (long ints)
- yield ('<%s%s><a href="%s"%s>%s</a></%s>' % \
+ result_id = smart_unicode(getattr(result, pk)) # conversion to string is needed in case of 23L (long ints)
+ yield (u'<%s%s><a href="%s"%s>%s</a></%s>' % \
(table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr, table_tag))
else:
- yield ('<td%s>%s</td>' % (row_class, result_repr))
+ yield (u'<td%s>%s</td>' % (row_class, result_repr))
def results(cl):
for res in cl.result_list:
View
25 django/contrib/admin/templatetags/admin_modify.py
@@ -2,6 +2,7 @@
from django.contrib.admin.views.main import AdminBoundField
from django.template import loader
from django.utils.text import capfirst
+from django.utils.encoding import smart_unicode
from django.db import models
from django.db.models.fields import Field
from django.db.models.related import BoundRelatedObject
@@ -14,7 +15,7 @@
absolute_url_re = re.compile(r'^(?:http(?:s)?:/)?/', re.IGNORECASE)
def class_name_to_underscored(name):
- return '_'.join([s.lower() for s in word_re.findall(name)[:-1]])
+ return u'_'.join([s.lower() for s in word_re.findall(name)[:-1]])
def include_admin_script(script_path):
"""
@@ -31,7 +32,7 @@ def include_admin_script(script_path):
"""
if not absolute_url_re.match(script_path):
script_path = '%s%s' % (settings.ADMIN_MEDIA_PREFIX, script_path)
- return '<script type="text/javascript" src="%s"></script>' % script_path
+ return u'<script type="text/javascript" src="%s"></script>' % script_path
include_admin_script = register.simple_tag(include_admin_script)
def submit_row(context):
@@ -61,8 +62,8 @@ def field_label(bound_field):
if not bound_field.first:
class_names.append('inline')
colon = ":"
- class_str = class_names and ' class="%s"' % ' '.join(class_names) or ''
- return '<label for="%s"%s>%s%s</label> ' % (bound_field.element_id, class_str, \
+ class_str = class_names and u' class="%s"' % u' '.join(class_names) or u''
+ return u'<label for="%s"%s>%s%s</label> ' % (bound_field.element_id, class_str, \
capfirst(bound_field.field.verbose_name), colon)
field_label = register.simple_tag(field_label)
@@ -77,7 +78,7 @@ def get_nodelist(cls, klass):
if klass not in cls.nodelists:
try:
field_class_name = klass.__name__
- template_name = "widget/%s.html" % class_name_to_underscored(field_class_name)
+ template_name = u"widget/%s.html" % class_name_to_underscored(field_class_name)
nodelist = loader.get_template(template_name).nodelist
except template.TemplateDoesNotExist:
super_klass = bool(klass.__bases__) and klass.__bases__[0] or None
@@ -175,30 +176,30 @@ def render(self, context):
return output
def output_all(form_fields):
- return ''.join([str(f) for f in form_fields])
+ return u''.join([smart_unicode(f) for f in form_fields])
output_all = register.simple_tag(output_all)
def auto_populated_field_script(auto_pop_fields, change = False):
t = []
for field in auto_pop_fields:
if change:
- t.append('document.getElementById("id_%s")._changed = true;' % field.name)
+ t.append(u'document.getElementById("id_%s")._changed = true;' % field.name)
else:
- t.append('document.getElementById("id_%s").onchange = function() { this._changed = true; };' % field.name)
+ t.append(u'document.getElementById("id_%s").onchange = function() { this._changed = true; };' % field.name)
- add_values = ' + " " + '.join(['document.getElementById("id_%s").value' % g for g in field.prepopulate_from])
+ add_values = u' + " " + '.join([u'document.getElementById("id_%s").value' % g for g in field.prepopulate_from])
for f in field.prepopulate_from:
- t.append('document.getElementById("id_%s").onkeyup = function() {' \
+ t.append(u'document.getElementById("id_%s").onkeyup = function() {' \
' var e = document.getElementById("id_%s");' \
' if(!e._changed) { e.value = URLify(%s, %s);} }; ' % (
f, field.name, add_values, field.maxlength))
- return ''.join(t)
+ return u''.join(t)
auto_populated_field_script = register.simple_tag(auto_populated_field_script)
def filter_interface_script_maybe(bound_field):
f = bound_field.field
if f.rel and isinstance(f.rel, models.ManyToManyRel) and f.rel.filter_interface:
- return '<script type="text/javascript">addEvent(window, "load", function(e) {' \
+ return u'<script type="text/javascript">addEvent(window, "load", function(e) {' \
' SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % (
f.name, f.verbose_name.replace('"', '\\"'), f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX)
else:
View
23 django/contrib/admin/views/main.py
@@ -12,6 +12,7 @@
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
import operator
from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION
@@ -142,7 +143,7 @@ def existing_display(self):
if isinstance(self.field.rel, models.ManyToOneRel):
self._display = getattr(self.original, self.field.name)
elif isinstance(self.field.rel, models.ManyToManyRel):
- self._display = ", ".join([str(obj) for obj in getattr(self.original, self.field.name).all()])
+ self._display = u", ".join([smart_unicode(obj) for obj in getattr(self.original, self.field.name).all()])
return self._display
def __repr__(self):
@@ -253,7 +254,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, str(new_object), ADDITION)
+ LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, smart_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.
@@ -266,7 +267,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, str(new_object).replace('"', '\\"')))
+ (pk_value, smart_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)
@@ -340,7 +341,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, str(new_object), CHANGE, change_message)
+ LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, smart_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:
@@ -443,11 +444,11 @@ 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(str(sub_obj))), []])
+ nh(deleted_objects, current_depth, ['%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>' % \
- (capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(), sub_obj._get_pk_val(), escape(str(sub_obj))), []])
+ (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
# permission to delete them, add the missing perm to perms_needed.
@@ -461,7 +462,7 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
opts_seen.append(related.opts)
rel_opts_name = related.get_accessor_name()
has_related_objs = False
-
+
# related.get_accessor_name() could return None for symmetrical relationships
if rel_opts_name:
rel_objs = getattr(obj, rel_opts_name, None)
@@ -474,13 +475,13 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
# Don't display link to edit, because it either has no
# admin or is edited inline.
nh(deleted_objects, current_depth, [_('One or more %(fieldname)s in %(name)s: %(obj)s') % \
- {'fieldname': related.field.verbose_name, 'name': related.opts.verbose_name, 'obj': escape(str(sub_obj))}, []])
+ {'fieldname': related.field.verbose_name, 'name': related.opts.verbose_name, 'obj': escape(sub_obj)}, []])
else:
# 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>' % \
- (related.opts.app_label, related.opts.module_name, sub_obj._get_pk_val(), escape(str(sub_obj)))), []])
+ (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:
@@ -501,14 +502,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(str(obj))), []]
+ deleted_objects = ['%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 = str(obj)
+ obj_display = smart_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})
Please sign in to comment.
Something went wrong with that request. Please try again.