1
0
mirror of https://github.com/django/django.git synced 2025-07-05 10:19:20 +00:00

unicode: Audited most of the remaining contrib/ modules for unicode compliance

(only sitemaps remaining). Fixes here for databrowse, markup and webdesign.


git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5274 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-05-17 01:24:58 +00:00
parent 5b4e2637f9
commit a8404e66fd
8 changed files with 81 additions and 41 deletions

View File

@ -3,10 +3,12 @@ These classes are light wrappers around Django's database API that provide
convenience functionality and permalink functions for the databrowse app. convenience functionality and permalink functions for the databrowse app.
""" """
import urllib
from django.db import models from django.db import models
from django.utils import dateformat from django.utils import dateformat
from django.utils.text import capfirst from django.utils.text import capfirst
from django.utils.translation import get_date_formats from django.utils.translation import get_date_formats
from django.utils.encoding import smart_unicode, smart_str
EMPTY_VALUE = '(None)' EMPTY_VALUE = '(None)'
@ -19,7 +21,7 @@ class EasyModel(object):
self.verbose_name_plural = model._meta.verbose_name_plural self.verbose_name_plural = model._meta.verbose_name_plural
def __repr__(self): def __repr__(self):
return '<EasyModel for %s>' % self.model._meta.object_name return '<EasyModel for %s>' % smart_str(self.model._meta.object_name)
def model_databrowse(self): def model_databrowse(self):
"Returns the ModelDatabrowse class for this model." "Returns the ModelDatabrowse class for this model."
@ -54,7 +56,7 @@ class EasyField(object):
self.model, self.field = easy_model, field self.model, self.field = easy_model, field
def __repr__(self): def __repr__(self):
return '<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name) return smart_str(u'<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
def choices(self): def choices(self):
for value, label in self.field.choices: for value, label in self.field.choices:
@ -72,29 +74,32 @@ class EasyChoice(object):
self.value, self.label = value, label self.value, self.label = value, label
def __repr__(self): def __repr__(self):
return '<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name) return smart_str(u'<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
def url(self): def url(self):
return '%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, self.value) return '%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, urllib.quote(smart_str(self.value)))
class EasyInstance(object): class EasyInstance(object):
def __init__(self, easy_model, instance): def __init__(self, easy_model, instance):
self.model, self.instance = easy_model, instance self.model, self.instance = easy_model, instance
def __repr__(self): def __repr__(self):
return '<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val()) return smart_str(u'<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val()))
def __unicode__(self):
val = smart_unicode(self.instance)
if len(val) > 30:
return val[:30] + u'...'
return val
def __str__(self): def __str__(self):
val = str(self.instance) return self.__unicode__().encode('utf-8')
if len(val) > 30:
return val[:30] + '...'
return val
def pk(self): def pk(self):
return self.instance._get_pk_val() return self.instance._get_pk_val()
def url(self): def url(self):
return '%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.pk()) return '%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, urllib.quote(smart_str(self.pk())))
def fields(self): def fields(self):
""" """
@ -126,7 +131,7 @@ class EasyInstanceField(object):
self.raw_value = getattr(instance.instance, field.name) self.raw_value = getattr(instance.instance, field.name)
def __repr__(self): def __repr__(self):
return '<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name) return smart_str(u'<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
def values(self): def values(self):
""" """
@ -175,18 +180,18 @@ class EasyInstanceField(object):
if self.field.rel.to in self.model.model_list: if self.field.rel.to in self.model.model_list:
lst = [] lst = []
for value in self.values(): for value in self.values():
url = '%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, value._get_pk_val()) url = '%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, urllib.quote(smart_str(value._get_pk_val())))
lst.append((str(value), url)) lst.append((smart_unicode(value), url))
else: else:
lst = [(value, None) for value in self.values()] lst = [(value, None) for value in self.values()]
elif self.field.choices: elif self.field.choices:
lst = [] lst = []
for value in self.values(): for value in self.values():
url = '%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, self.raw_value) url = '%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, urllib.quote(smart_str(self.raw_value)))
lst.append((value, url)) lst.append((value, url))
elif isinstance(self.field, models.URLField): elif isinstance(self.field, models.URLField):
val = self.values()[0] val = self.values()[0]
lst = [(val, val)] lst = [(val, urllib.quote(smart_str(val)))]
else: else:
lst = [(self.values()[0], None)] lst = [(self.values()[0], None)]
return lst return lst

View File

@ -27,13 +27,13 @@ class CalendarPlugin(DatabrowsePlugin):
def model_index_html(self, request, model, site): def model_index_html(self, request, model, site):
fields = self.field_dict(model) fields = self.field_dict(model)
if not fields: if not fields:
return '' return u''
return '<p class="filter"><strong>View calendar by:</strong> %s</p>' % \ return u'<p class="filter"><strong>View calendar by:</strong> %s</p>' % \
', '.join(['<a href="calendars/%s/">%s</a>' % (f.name, capfirst(f.verbose_name)) for f in fields.values()]) u', '.join(['<a href="calendars/%s/">%s</a>' % (f.name, capfirst(f.verbose_name)) for f in fields.values()])
def urls(self, plugin_name, easy_instance_field): def urls(self, plugin_name, easy_instance_field):
if isinstance(easy_instance_field.field, models.DateField): if isinstance(easy_instance_field.field, models.DateField):
return ['%s%s/%s/%s/%s/%s/' % (easy_instance_field.model.url(), return [u'%s%s/%s/%s/%s/%s/' % (easy_instance_field.model.url(),
plugin_name, easy_instance_field.field.name, plugin_name, easy_instance_field.field.name,
easy_instance_field.raw_value.year, easy_instance_field.raw_value.year,
easy_instance_field.raw_value.strftime('%b').lower(), easy_instance_field.raw_value.strftime('%b').lower(),

View File

@ -4,9 +4,11 @@ from django.contrib.databrowse.datastructures import EasyModel
from django.contrib.databrowse.sites import DatabrowsePlugin from django.contrib.databrowse.sites import DatabrowsePlugin
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.utils.text import capfirst from django.utils.text import capfirst
from django.utils.encoding import smart_str
from django.views.generic import date_based from django.views.generic import date_based
import datetime import datetime
import time import time
import urllib
class FieldChoicePlugin(DatabrowsePlugin): class FieldChoicePlugin(DatabrowsePlugin):
def __init__(self, field_filter=None): def __init__(self, field_filter=None):
@ -29,15 +31,15 @@ class FieldChoicePlugin(DatabrowsePlugin):
def model_index_html(self, request, model, site): def model_index_html(self, request, model, site):
fields = self.field_dict(model) fields = self.field_dict(model)
if not fields: if not fields:
return '' return u''
return '<p class="filter"><strong>View by:</strong> %s</p>' % \ return u'<p class="filter"><strong>View by:</strong> %s</p>' % \
', '.join(['<a href="fields/%s/">%s</a>' % (f.name, capfirst(f.verbose_name)) for f in fields.values()]) u', '.join(['<a href="fields/%s/">%s</a>' % (f.name, capfirst(f.verbose_name)) for f in fields.values()])
def urls(self, plugin_name, easy_instance_field): def urls(self, plugin_name, easy_instance_field):
if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values(): if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values():
return ['%s%s/%s/%s/' % (easy_instance_field.model.url(), return [u'%s%s/%s/%s/' % (easy_instance_field.model.url(),
plugin_name, easy_instance_field.field.name, plugin_name, easy_instance_field.field.name,
easy_instance_field.raw_value)] urllib.quote(smart_str(easy_instance_field.raw_value)))]
def model_view(self, request, model_databrowse, url): def model_view(self, request, model_databrowse, url):
self.model, self.site = model_databrowse.model, model_databrowse.site self.model, self.site = model_databrowse.model, model_databrowse.site

View File

@ -60,7 +60,7 @@ class ModelDatabrowse(object):
def main_view(self, request): def main_view(self, request):
easy_model = EasyModel(self.site, self.model) easy_model = EasyModel(self.site, self.model)
html_snippets = '\n'.join([p.model_index_html(request, self.model, self.site) for p in self.plugins.values()]) html_snippets = u'\n'.join([p.model_index_html(request, self.model, self.site) for p in self.plugins.values()])
return render_to_response('databrowse/model_detail.html', { return render_to_response('databrowse/model_detail.html', {
'model': easy_model, 'model': easy_model,
'root_url': self.site.root_url, 'root_url': self.site.root_url,

View File

@ -10,7 +10,7 @@
<ul class="objectlist"> <ul class="objectlist">
{% for object in object_list %} {% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object }}/">{{ object|escape }}</a></li> <li class="{% cycle odd,even %}"><a href="{{ object|urlencode }}/">{{ object|escape }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>

View File

@ -16,6 +16,7 @@ silently fail and return the un-marked-up text.
from django import template from django import template
from django.conf import settings from django.conf import settings
from django.utils.encoding import smart_str, smart_unicode
register = template.Library() register = template.Library()
@ -25,9 +26,9 @@ def textile(value):
except ImportError: except ImportError:
if settings.DEBUG: if settings.DEBUG:
raise template.TemplateSyntaxError, "Error in {% textile %} filter: The Python textile library isn't installed." raise template.TemplateSyntaxError, "Error in {% textile %} filter: The Python textile library isn't installed."
return value return smart_unicode(value)
else: else:
return textile.textile(value, encoding=settings.DEFAULT_CHARSET, output=settings.DEFAULT_CHARSET) return smart_unicode(textile.textile(smart_str(value), encoding='utf-8', output='utf-8'))
def markdown(value): def markdown(value):
try: try:
@ -35,9 +36,9 @@ def markdown(value):
except ImportError: except ImportError:
if settings.DEBUG: if settings.DEBUG:
raise template.TemplateSyntaxError, "Error in {% markdown %} filter: The Python markdown library isn't installed." raise template.TemplateSyntaxError, "Error in {% markdown %} filter: The Python markdown library isn't installed."
return value return smart_unicode(value)
else: else:
return markdown.markdown(value) return smart_unicode(markdown.markdown(smart_str(value)))
def restructuredtext(value): def restructuredtext(value):
try: try:
@ -45,11 +46,11 @@ def restructuredtext(value):
except ImportError: except ImportError:
if settings.DEBUG: if settings.DEBUG:
raise template.TemplateSyntaxError, "Error in {% restructuredtext %} filter: The Python docutils library isn't installed." raise template.TemplateSyntaxError, "Error in {% restructuredtext %} filter: The Python docutils library isn't installed."
return value return smart_unicode(value)
else: else:
docutils_settings = getattr(settings, "RESTRUCTUREDTEXT_FILTER_SETTINGS", {}) docutils_settings = getattr(settings, "RESTRUCTUREDTEXT_FILTER_SETTINGS", {})
parts = publish_parts(source=value, writer_name="html4css1", settings_overrides=docutils_settings) parts = publish_parts(source=smart_str(value), writer_name="html4css1", settings_overrides=docutils_settings)
return parts["fragment"] return smart_unicode(parts["fragment"])
register.filter(textile) register.filter(textile)
register.filter(markdown) register.filter(markdown)

View File

@ -5,8 +5,40 @@ Utility functions for generating "lorem ipsum" Latin text.
import random import random
COMMON_P = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' COMMON_P = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
WORDS = ('exercitationem', 'perferendis', 'perspiciatis', 'laborum', 'eveniet', 'sunt', 'iure', 'nam', 'nobis', 'eum', 'cum', 'officiis', 'excepturi', 'odio', 'consectetur', 'quasi', 'aut', 'quisquam', 'vel', 'eligendi', 'itaque', 'non', 'odit', 'tempore', 'quaerat', 'dignissimos', 'facilis', 'neque', 'nihil', 'expedita', 'vitae', 'vero', 'ipsum', 'nisi', 'animi', 'cumque', 'pariatur', 'velit', 'modi', 'natus', 'iusto', 'eaque', 'sequi', 'illo', 'sed', 'ex', 'et', 'voluptatibus', 'tempora', 'veritatis', 'ratione', 'assumenda', 'incidunt', 'nostrum', 'placeat', 'aliquid', 'fuga', 'provident', 'praesentium', 'rem', 'necessitatibus', 'suscipit', 'adipisci', 'quidem', 'possimus', 'voluptas', 'debitis', 'sint', 'accusantium', 'unde', 'sapiente', 'voluptate', 'qui', 'aspernatur', 'laudantium', 'soluta', 'amet', 'quo', 'aliquam', 'saepe', 'culpa', 'libero', 'ipsa', 'dicta', 'reiciendis', 'nesciunt', 'doloribus', 'autem', 'impedit', 'minima', 'maiores', 'repudiandae', 'ipsam', 'obcaecati', 'ullam', 'enim', 'totam', 'delectus', 'ducimus', 'quis', 'voluptates', 'dolores', 'molestiae', 'harum', 'dolorem', 'quia', 'voluptatem', 'molestias', 'magni', 'distinctio', 'omnis', 'illum', 'dolorum', 'voluptatum', 'ea', 'quas', 'quam', 'corporis', 'quae', 'blanditiis', 'atque', 'deserunt', 'laboriosam', 'earum', 'consequuntur', 'hic', 'cupiditate', 'quibusdam', 'accusamus', 'ut', 'rerum', 'error', 'minus', 'eius', 'ab', 'ad', 'nemo', 'fugit', 'officia', 'at', 'in', 'id', 'quos', 'reprehenderit', 'numquam', 'iste', 'fugiat', 'sit', 'inventore', 'beatae', 'repellendus', 'magnam', 'recusandae', 'quod', 'explicabo', 'doloremque', 'aperiam', 'consequatur', 'asperiores', 'commodi', 'optio', 'dolor', 'labore', 'temporibus', 'repellat', 'veniam', 'architecto', 'est', 'esse', 'mollitia', 'nulla', 'a', 'similique', 'eos', 'alias', 'dolore', 'tenetur', 'deleniti', 'porro', 'facere', 'maxime', 'corrupti')
COMMON_WORDS = ('lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipisicing', 'elit', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua') WORDS = ('exercitationem', 'perferendis', 'perspiciatis', 'laborum', 'eveniet',
'sunt', 'iure', 'nam', 'nobis', 'eum', 'cum', 'officiis', 'excepturi',
'odio', 'consectetur', 'quasi', 'aut', 'quisquam', 'vel', 'eligendi',
'itaque', 'non', 'odit', 'tempore', 'quaerat', 'dignissimos',
'facilis', 'neque', 'nihil', 'expedita', 'vitae', 'vero', 'ipsum',
'nisi', 'animi', 'cumque', 'pariatur', 'velit', 'modi', 'natus',
'iusto', 'eaque', 'sequi', 'illo', 'sed', 'ex', 'et', 'voluptatibus',
'tempora', 'veritatis', 'ratione', 'assumenda', 'incidunt', 'nostrum',
'placeat', 'aliquid', 'fuga', 'provident', 'praesentium', 'rem',
'necessitatibus', 'suscipit', 'adipisci', 'quidem', 'possimus',
'voluptas', 'debitis', 'sint', 'accusantium', 'unde', 'sapiente',
'voluptate', 'qui', 'aspernatur', 'laudantium', 'soluta', 'amet',
'quo', 'aliquam', 'saepe', 'culpa', 'libero', 'ipsa', 'dicta',
'reiciendis', 'nesciunt', 'doloribus', 'autem', 'impedit', 'minima',
'maiores', 'repudiandae', 'ipsam', 'obcaecati', 'ullam', 'enim',
'totam', 'delectus', 'ducimus', 'quis', 'voluptates', 'dolores',
'molestiae', 'harum', 'dolorem', 'quia', 'voluptatem', 'molestias',
'magni', 'distinctio', 'omnis', 'illum', 'dolorum', 'voluptatum', 'ea',
'quas', 'quam', 'corporis', 'quae', 'blanditiis', 'atque', 'deserunt',
'laboriosam', 'earum', 'consequuntur', 'hic', 'cupiditate',
'quibusdam', 'accusamus', 'ut', 'rerum', 'error', 'minus', 'eius',
'ab', 'ad', 'nemo', 'fugit', 'officia', 'at', 'in', 'id', 'quos',
'reprehenderit', 'numquam', 'iste', 'fugiat', 'sit', 'inventore',
'beatae', 'repellendus', 'magnam', 'recusandae', 'quod', 'explicabo',
'doloremque', 'aperiam', 'consequatur', 'asperiores', 'commodi',
'optio', 'dolor', 'labore', 'temporibus', 'repellat', 'veniam',
'architecto', 'est', 'esse', 'mollitia', 'nulla', 'a', 'similique',
'eos', 'alias', 'dolore', 'tenetur', 'deleniti', 'porro', 'facere',
'maxime', 'corrupti')
COMMON_WORDS = ('lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur',
'adipisicing', 'elit', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt',
'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua')
def sentence(): def sentence():
""" """
@ -17,10 +49,10 @@ def sentence():
""" """
# Determine the number of comma-separated sections and number of words in # Determine the number of comma-separated sections and number of words in
# each section for this sentence. # each section for this sentence.
sections = [' '.join(random.sample(WORDS, random.randint(3, 12))) for i in range(random.randint(1, 5))] sections = [u' '.join(random.sample(WORDS, random.randint(3, 12))) for i in range(random.randint(1, 5))]
s = ', '.join(sections) s = u', '.join(sections)
# Convert to sentence case and add end punctuation. # Convert to sentence case and add end punctuation.
return '%s%s%s' % (s[0].upper(), s[1:], random.choice('?.')) return u'%s%s%s' % (s[0].upper(), s[1:], random.choice('?.'))
def paragraph(): def paragraph():
""" """
@ -28,7 +60,7 @@ def paragraph():
The paragraph consists of between 1 and 4 sentences, inclusive. The paragraph consists of between 1 and 4 sentences, inclusive.
""" """
return ' '.join([sentence() for i in range(random.randint(1, 4))]) return u' '.join([sentence() for i in range(random.randint(1, 4))])
def paragraphs(count, common=True): def paragraphs(count, common=True):
""" """
@ -66,4 +98,4 @@ def words(count, common=True):
word_list += random.sample(WORDS, c) word_list += random.sample(WORDS, c)
else: else:
word_list = word_list[:count] word_list = word_list[:count]
return ' '.join(word_list) return u' '.join(word_list)

View File

@ -18,7 +18,7 @@ class LoremNode(template.Node):
paras = paragraphs(count, common=self.common) paras = paragraphs(count, common=self.common)
if self.method == 'p': if self.method == 'p':
paras = ['<p>%s</p>' % p for p in paras] paras = ['<p>%s</p>' % p for p in paras]
return '\n\n'.join(paras) return u'\n\n'.join(paras)
#@register.tag #@register.tag
def lorem(parser, token): def lorem(parser, token):