From cb09e10eb2634243f25ae61e439a71ca47d98884 Mon Sep 17 00:00:00 2001 From: Georg Bauer Date: Thu, 6 Oct 2005 10:04:07 +0000 Subject: [PATCH] i18n: merged r776:r786 from trunk git-svn-id: http://code.djangoproject.com/svn/django/branches/i18n@787 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/conf/global_settings.py | 11 +++++++--- django/core/formfields.py | 7 +++--- django/core/handlers/modpython.py | 5 +++-- django/core/handlers/wsgi.py | 2 +- django/core/management.py | 33 +++++++++++++++++++--------- django/core/template.py | 3 ++- django/middleware/cache.py | 2 +- django/middleware/common.py | 36 +++++++++++++++---------------- django/utils/httpwrappers.py | 6 +++--- django/views/admin/main.py | 2 +- django/views/decorators/cache.py | 3 ++- docs/db-api.txt | 5 +++++ 12 files changed, 70 insertions(+), 45 deletions(-) diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 4204c7a25d..6278ae6656 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -42,9 +42,11 @@ LANGUAGES = ( # notifications and other various e-mails. MANAGERS = ADMINS -# Default MIME type to use for all HttpResponse objects, if a MIME type -# isn't manually specified. This is directly used as the Content-Type header. -DEFAULT_MIME_TYPE = 'text/html; charset=utf-8' +# Default content type and charset to use for all HttpResponse objects, if a +# MIME type isn't manually specified. These are used to construct the +# Content-Type header. +DEFAULT_CONTENT_TYPE = 'text/html' +DEFAULT_CHARSET = 'utf-8' # E-mail address that error messages come from. SERVER_EMAIL = 'root@localhost' @@ -110,6 +112,9 @@ ALLOWED_INCLUDE_ROOTS = () # is an admin. ADMIN_FOR = [] +# Whether to check the flat-pages table as a last resort for all 404 errors. +USE_FLAT_PAGES = True + # 404s that may be ignored. IGNORABLE_404_STARTS = ('/cgi-bin/', '/_vti_bin', '/_vti_inf') IGNORABLE_404_ENDS = ('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php') diff --git a/django/core/formfields.py b/django/core/formfields.py index 7587b67170..76721ba5c6 100644 --- a/django/core/formfields.py +++ b/django/core/formfields.py @@ -1,6 +1,7 @@ from django.core import validators from django.core.exceptions import PermissionDenied from django.utils.html import escape +from django.conf.settings import DEFAULT_CHARSET FORM_FIELD_ID_PREFIX = 'id_' @@ -221,7 +222,7 @@ class TextField(FormField): self.validator_list = [self.isValidLength, self.hasNoNewlines] + validator_list def isValidLength(self, data, form): - if data and self.maxlength and len(data) > self.maxlength: + if data and self.maxlength and len(data.decode(DEFAULT_CHARSET)) > self.maxlength: raise validators.ValidationError, "Ensure your text is less than %s characters." % self.maxlength def hasNoNewlines(self, data, form): @@ -235,7 +236,7 @@ class TextField(FormField): if self.maxlength: maxlength = 'maxlength="%s" ' % self.maxlength if isinstance(data, unicode): - data = data.encode('utf-8') + data = data.encode(DEFAULT_CHARSET) return '' % \ (FORM_FIELD_ID_PREFIX + self.field_name, self.__class__.__name__, self.is_required and ' required' or '', self.field_name, self.length, escape(data), maxlength) @@ -264,7 +265,7 @@ class LargeTextField(TextField): if data is None: data = '' if isinstance(data, unicode): - data = data.encode('utf-8') + data = data.encode(DEFAULT_CHARSET) return '' % \ (FORM_FIELD_ID_PREFIX + self.field_name, self.__class__.__name__, self.is_required and ' required' or '', self.field_name, self.rows, self.cols, escape(data)) diff --git a/django/core/handlers/modpython.py b/django/core/handlers/modpython.py index 623db959b2..e52879065f 100644 --- a/django/core/handlers/modpython.py +++ b/django/core/handlers/modpython.py @@ -150,14 +150,15 @@ class ModPythonHandler(BaseHandler): def populate_apache_request(http_response, mod_python_req): "Populates the mod_python request object with an HttpResponse" - mod_python_req.content_type = http_response['Content-Type'] or httpwrappers.DEFAULT_MIME_TYPE + from django.conf import settings + mod_python_req.content_type = http_response['Content-Type'] for key, value in http_response.headers.items(): if key != 'Content-Type': mod_python_req.headers_out[key] = value for c in http_response.cookies.values(): mod_python_req.headers_out.add('Set-Cookie', c.output(header='')) mod_python_req.status = http_response.status_code - mod_python_req.write(http_response.get_content_as_string('utf-8')) + mod_python_req.write(http_response.get_content_as_string(settings.DEFAULT_CHARSET)) def handler(req): # mod_python hooks into this function. diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py index 40ea9fb902..2d34c64821 100644 --- a/django/core/handlers/wsgi.py +++ b/django/core/handlers/wsgi.py @@ -167,6 +167,6 @@ class WSGIHandler(BaseHandler): response_headers = response.headers.items() for c in response.cookies.values(): response_headers.append(('Set-Cookie', c.output(header=''))) - output = [response.get_content_as_string('utf-8')] + output = [response.get_content_as_string(settings.DEFAULT_CHARSET)] start_response(status, response_headers) return output diff --git a/django/core/management.py b/django/core/management.py index f3accd84cc..fe7fca6b17 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -549,16 +549,29 @@ def get_validation_errors(outfile): if not isinstance(opts.admin, meta.Admin): e.add(opts, '"admin" attribute, if given, must be set to a meta.Admin() instance.') else: - for fn in opts.admin.list_display: - try: - f = opts.get_field(fn) - except meta.FieldDoesNotExist: - klass = opts.get_model_module().Klass - if not hasattr(klass, fn) or not callable(getattr(klass, fn)): - e.add(opts, '"admin.list_display" refers to %r, which isn\'t a field or method.' % fn) - else: - if isinstance(f, meta.ManyToManyField): - e.add(opts, '"admin.list_display" doesn\'t support ManyToManyFields (%r).' % fn) + # list_display + if not isinstance(opts.admin.list_display, (list, tuple)): + e.add(opts, '"admin.list_display", if given, must be set to a list or tuple.') + else: + for fn in opts.admin.list_display: + try: + f = opts.get_field(fn) + except meta.FieldDoesNotExist: + klass = opts.get_model_module().Klass + if not hasattr(klass, fn) or not callable(getattr(klass, fn)): + e.add(opts, '"admin.list_display" refers to %r, which isn\'t a field or method.' % fn) + else: + if isinstance(f, meta.ManyToManyField): + e.add(opts, '"admin.list_display" doesn\'t support ManyToManyFields (%r).' % fn) + # list_filter + if not isinstance(opts.admin.list_filter, (list, tuple)): + e.add(opts, '"admin.list_filter", if given, must be set to a list or tuple.') + else: + for fn in opts.admin.list_filter: + try: + f = opts.get_field(fn) + except meta.FieldDoesNotExist: + e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn) # Check ordering attribute. if opts.ordering: diff --git a/django/core/template.py b/django/core/template.py index d23e3f6a71..11ce3b2ce1 100644 --- a/django/core/template.py +++ b/django/core/template.py @@ -55,6 +55,7 @@ times with multiple contexts) '\n\n\n\n' """ import re +from django.conf.settings import DEFAULT_CHARSET __all__ = ('Template','Context','compile_string') @@ -519,7 +520,7 @@ class VariableNode(Node): if not isinstance(output, basestring): output = str(output) elif isinstance(output, unicode): - output = output.encode('utf-8') + output = output.encode(DEFAULT_CHARSET) return output def register_tag(token_command, callback_function): diff --git a/django/middleware/cache.py b/django/middleware/cache.py index f3d03e657a..7f4057eec7 100644 --- a/django/middleware/cache.py +++ b/django/middleware/cache.py @@ -76,7 +76,7 @@ class CacheMiddleware: Sets the cache, if needed. """ if request._cache_middleware_set_cache: - content = response.get_content_as_string('utf-8') + content = response.get_content_as_string(settings.DEFAULT_CHARSET) if request._cache_middleware_accepts_gzip: content = compress_string(content) response.content = content diff --git a/django/middleware/common.py b/django/middleware/common.py index ee6b68be7e..e794477b62 100644 --- a/django/middleware/common.py +++ b/django/middleware/common.py @@ -54,31 +54,29 @@ class CommonMiddleware: return None def process_response(self, request, response): - """ - Check for a flatfile (for 404s) and calculate the Etag, if needed. - """ - - # If this was a 404, check for a flat file + "Check for a flat page (for 404s) and calculate the Etag, if needed." if response.status_code == 404: - try: - response = flat_file(request, request.path) - except exceptions.Http404: + if settings.USE_FLAT_PAGES: + try: + return flat_file(request, request.path) + except exceptions.Http404: + pass + + if settings.SEND_BROKEN_LINK_EMAILS: # If the referrer was from an internal link or a non-search-engine site, # send a note to the managers. - if settings.SEND_BROKEN_LINK_EMAILS: - domain = request.META['HTTP_HOST'] - referer = request.META.get('HTTP_REFERER', None) - is_internal = referer and (domain in referer) - path = request.get_full_path() - if referer and not _is_ignorable_404(path) and (is_internal or '?' not in referer): - mail_managers("Broken %slink on %s" % ((is_internal and 'INTERNAL ' or ''), domain), - "Referrer: %s\nRequested URL: %s\n" % (referer, request.get_full_path())) - # If there's no flatfile we want to return the original 404 response + domain = request.META['HTTP_HOST'] + referer = request.META.get('HTTP_REFERER', None) + is_internal = referer and (domain in referer) + path = request.get_full_path() + if referer and not _is_ignorable_404(path) and (is_internal or '?' not in referer): + mail_managers("Broken %slink on %s" % ((is_internal and 'INTERNAL ' or ''), domain), + "Referrer: %s\nRequested URL: %s\n" % (referer, request.get_full_path())) return response - # Use ETags, if requested + # Use ETags, if requested. if settings.USE_ETAGS: - etag = md5.new(response.get_content_as_string('utf-8')).hexdigest() + etag = md5.new(response.get_content_as_string(settings.DEFAULT_CHARSET)).hexdigest() if request.META.get('HTTP_IF_NONE_MATCH') == etag: response = httpwrappers.HttpResponseNotModified() else: diff --git a/django/utils/httpwrappers.py b/django/utils/httpwrappers.py index eeebda565d..5f9362bd24 100644 --- a/django/utils/httpwrappers.py +++ b/django/utils/httpwrappers.py @@ -1,7 +1,7 @@ from Cookie import SimpleCookie from pprint import pformat from urllib import urlencode -import datastructures +from django.utils import datastructures class HttpRequest(object): # needs to be new-style class because subclasses define "property"s "A basic HTTP request" @@ -139,8 +139,8 @@ class HttpResponse: "A basic HTTP response, with content and dictionary-accessed headers" def __init__(self, content='', mimetype=None): if not mimetype: - from django.conf.settings import DEFAULT_MIME_TYPE - mimetype = DEFAULT_MIME_TYPE + from django.conf.settings import DEFAULT_CONTENT_TYPE, DEFAULT_CHARSET + mimetype = "%s; charset=%s" % (DEFAULT_CONTENT_TYPE, DEFAULT_CHARSET) self.content = content self.headers = {'Content-Type':mimetype} self.cookies = SimpleCookie() diff --git a/django/views/admin/main.py b/django/views/admin/main.py index 9283230b26..c58da1fbca 100644 --- a/django/views/admin/main.py +++ b/django/views/admin/main.py @@ -431,7 +431,7 @@ def change_list(request, app_label, module_name): if j == 0: # First column is a special case result_id = getattr(result, pk) raw_template.append('%s' % \ - (row_class, result_id, (is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %s); return false;"' % result_id or ''), result_repr)) + (row_class, result_id, (is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr)) else: raw_template.append('%s' % (row_class, result_repr)) raw_template.append('\n') diff --git a/django/views/decorators/cache.py b/django/views/decorators/cache.py index 7c76ef272d..de80851363 100644 --- a/django/views/decorators/cache.py +++ b/django/views/decorators/cache.py @@ -1,6 +1,7 @@ from django.core.cache import cache from django.utils.httpwrappers import HttpResponseNotModified from django.utils.text import compress_string +from django.conf.settings import DEFAULT_CHARSET import datetime, md5 def cache_page(view_func, cache_timeout, key_prefix=''): @@ -25,7 +26,7 @@ def cache_page(view_func, cache_timeout, key_prefix=''): response = cache.get(cache_key, None) if response is None: response = view_func(request, *args, **kwargs) - content = response.get_content_as_string('utf-8') + content = response.get_content_as_string(DEFAULT_CHARSET) if accepts_gzip: content = compress_string(content) response.content = content diff --git a/docs/db-api.txt b/docs/db-api.txt index e0885da8f0..8a02437aaa 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -572,6 +572,9 @@ object in the result list is "truncated" to the given ``type``. * ``"month"`` returns a list of all distinct year/month values for the field. * ``"day"`` returns a list of all distinct year/month/day values for the field. +Additional, optional keyword arguments, in the format described in +"Field lookups" above, are also accepted. + Here's an example, using the ``Poll`` model defined above:: >>> from datetime import datetime @@ -587,6 +590,8 @@ Here's an example, using the ``Poll`` model defined above:: [datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)] >>> polls.get_pub_date_list('day') [datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)] + >>> polls.get_pub_date_list('day', question__contains='name') + [datetime.datetime(2005, 3, 20)] ``get_FOO_list()`` also accepts an optional keyword argument ``order``, which should be either ``"ASC"`` or ``"DESC"``. This specifies how to order the