Author: mtredinnick
Date: 2007-05-12 05:34:34 -0500 (Sat, 12 May 2007)
New Revision: 5200

Modified:
   django/branches/unicode/django/contrib/admin/filterspecs.py
   django/branches/unicode/django/contrib/admin/models.py
   django/branches/unicode/django/contrib/admin/templatetags/admin_list.py
   django/branches/unicode/django/contrib/admin/templatetags/admin_modify.py
   django/branches/unicode/django/contrib/admin/views/main.py
Log:
unicode: Adjusted the admin interface to handle unicode strings. May still need
some tweaking, but the bulk of it should be correct. Fixed #4266.


Modified: django/branches/unicode/django/contrib/admin/filterspecs.py
===================================================================
--- django/branches/unicode/django/contrib/admin/filterspecs.py 2007-05-12 
06:54:41 UTC (rev 5199)
+++ django/branches/unicode/django/contrib/admin/filterspecs.py 2007-05-12 
10:34:34 UTC (rev 5200)
@@ -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 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 @@
                '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 @@
                '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 @@
                '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}

Modified: django/branches/unicode/django/contrib/admin/models.py
===================================================================
--- django/branches/unicode/django/contrib/admin/models.py      2007-05-12 
06:54:41 UTC (rev 5199)
+++ django/branches/unicode/django/contrib/admin/models.py      2007-05-12 
10:34:34 UTC (rev 5200)
@@ -28,7 +28,7 @@
         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 @@
         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)

Modified: 
django/branches/unicode/django/contrib/admin/templatetags/admin_list.py
===================================================================
--- django/branches/unicode/django/contrib/admin/templatetags/admin_list.py     
2007-05-12 06:54:41 UTC (rev 5199)
+++ django/branches/unicode/django/contrib/admin/templatetags/admin_list.py     
2007-05-12 10:34:34 UTC (rev 5200)
@@ -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 @@
             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 _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 @@
                     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 @@
             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:

Modified: 
django/branches/unicode/django/contrib/admin/templatetags/admin_modify.py
===================================================================
--- django/branches/unicode/django/contrib/admin/templatetags/admin_modify.py   
2007-05-12 06:54:41 UTC (rev 5199)
+++ django/branches/unicode/django/contrib/admin/templatetags/admin_modify.py   
2007-05-12 10:34:34 UTC (rev 5200)
@@ -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 @@
     """
     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 @@
         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 @@
         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 @@
         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:

Modified: django/branches/unicode/django/contrib/admin/views/main.py
===================================================================
--- django/branches/unicode/django/contrib/admin/views/main.py  2007-05-12 
06:54:41 UTC (rev 5199)
+++ django/branches/unicode/django/contrib/admin/views/main.py  2007-05-12 
10:34:34 UTC (rev 5200)
@@ -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 @@
             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 @@
         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 @@
                 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 @@
             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 @@
                 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 @@
         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 @@
                     # 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 @@
 
     # 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})


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to