From 6104f6bd856a36e41352d3b90e7a550ef276daab Mon Sep 17 00:00:00 2001 From: Joseph Kocherhans Date: Sat, 6 Oct 2007 22:34:48 +0000 Subject: [PATCH] newforms-admin: Merged to [6458] git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@6459 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 4 +- django/bin/compile-messages.py | 3 +- django/bin/make-messages.py | 95 ++++++++-------- django/conf/locale/de/LC_MESSAGES/django.mo | Bin 44119 -> 44534 bytes django/conf/locale/de/LC_MESSAGES/django.po | 67 ++++++------ django/contrib/auth/backends.py | 5 + django/contrib/sessions/models.py | 9 +- django/core/handlers/wsgi.py | 17 +-- django/core/management/__init__.py | 2 +- django/core/management/commands/startapp.py | 2 +- django/db/models/fields/__init__.py | 2 +- django/http/__init__.py | 5 +- django/newforms/widgets.py | 18 ++- django/oldforms/__init__.py | 4 +- django/utils/cache.py | 15 ++- django/utils/translation/__init__.py | 14 ++- django/utils/translation/trans_null.py | 1 - django/utils/translation/trans_real.py | 6 - django/views/static.py | 4 +- docs/databases.txt | 115 ++++++++++++++++++++ docs/email.txt | 2 +- docs/install.txt | 2 + docs/newforms.txt | 4 +- tests/modeltests/basic/models.py | 2 +- tests/modeltests/field_defaults/models.py | 2 +- tests/regressiontests/i18n/models.py | 12 ++ tests/regressiontests/i18n/tests.py | 8 ++ 27 files changed, 294 insertions(+), 126 deletions(-) diff --git a/AUTHORS b/AUTHORS index f175a1034b..f5c35fb9f8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -115,6 +115,7 @@ answer newbie questions, and generally made Django that much better: Enrico A. Murat Eren Ludvig Ericson + eriks@win.tue.nl Dirk Eschler Marc Fargas Szilveszter Farkas @@ -239,6 +240,7 @@ answer newbie questions, and generally made Django that much better: Jay Parlar pavithran s Barry Pederson + permonik@mesias.brnonet.cz petr.marhoun@gmail.com pgross@thoughtworks.com phaedo @@ -317,7 +319,7 @@ answer newbie questions, and generally made Django that much better: Vlado Milton Waddams wam-djangobug@wamber.net - wangchun + Wang Chun Filip Wasilewski Dan Watson Chris Wesseling diff --git a/django/bin/compile-messages.py b/django/bin/compile-messages.py index 2838cb8aa4..8693022644 100755 --- a/django/bin/compile-messages.py +++ b/django/bin/compile-messages.py @@ -14,7 +14,8 @@ def compile_messages(locale=None): basedirs = [os.path.join('conf', 'locale'), 'locale'] if os.environ.get('DJANGO_SETTINGS_MODULE'): from django.conf import settings - basedirs += settings.LOCALE_PATHS + if hasattr(settings, 'LOCALE_PATHS'): + basedirs += settings.LOCALE_PATHS # Gather existing directories. basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs))) diff --git a/django/bin/make-messages.py b/django/bin/make-messages.py index 11616c9ca5..44040390ea 100755 --- a/django/bin/make-messages.py +++ b/django/bin/make-messages.py @@ -74,59 +74,62 @@ def make_messages(): if os.path.exists(potfile): os.unlink(potfile) + all_files = [] for (dirpath, dirnames, filenames) in os.walk("."): - for file in filenames: - if domain == 'djangojs' and file.endswith('.js'): - if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) + all_files.extend([(dirpath, f) for f in filenames]) + all_files.sort() + for dirpath, file in all_files: + if domain == 'djangojs' and file.endswith('.js'): + if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) + src = open(os.path.join(dirpath, file), "rb").read() + src = pythonize_re.sub('\n#', src) + open(os.path.join(dirpath, '%s.py' % file), "wb").write(src) + thefile = '%s.py' % file + cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % ( + os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile)) + (stdin, stdout, stderr) = os.popen3(cmd, 't') + msgs = stdout.read() + errors = stderr.read() + if errors: + print "errors happened while running xgettext on %s" % file + print errors + sys.exit(8) + old = '#: '+os.path.join(dirpath, thefile)[2:] + new = '#: '+os.path.join(dirpath, file)[2:] + msgs = msgs.replace(old, new) + if msgs: + open(potfile, 'ab').write(msgs) + os.unlink(os.path.join(dirpath, thefile)) + elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')): + thefile = file + if file.endswith('.html'): src = open(os.path.join(dirpath, file), "rb").read() - src = pythonize_re.sub('\n#', src) - open(os.path.join(dirpath, '%s.py' % file), "wb").write(src) thefile = '%s.py' % file - cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % ( - os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile)) - (stdin, stdout, stderr) = os.popen3(cmd, 't') - msgs = stdout.read() - errors = stderr.read() - if errors: - print "errors happened while running xgettext on %s" % file - print errors - sys.exit(8) + open(os.path.join(dirpath, thefile), "wb").write(templatize(src)) + if verbose: + sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) + cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % ( + domain, os.path.join(dirpath, thefile)) + (stdin, stdout, stderr) = os.popen3(cmd, 't') + msgs = stdout.read() + errors = stderr.read() + if errors: + print "errors happened while running xgettext on %s" % file + print errors + sys.exit(8) + if thefile != file: old = '#: '+os.path.join(dirpath, thefile)[2:] new = '#: '+os.path.join(dirpath, file)[2:] msgs = msgs.replace(old, new) - if msgs: - open(potfile, 'ab').write(msgs) + if os.path.exists(potfile): + # Strip the header + msgs = '\n'.join(dropwhile(len, msgs.split('\n'))) + else: + msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8') + if msgs: + open(potfile, 'ab').write(msgs) + if thefile != file: os.unlink(os.path.join(dirpath, thefile)) - elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')): - thefile = file - if file.endswith('.html'): - src = open(os.path.join(dirpath, file), "rb").read() - thefile = '%s.py' % file - open(os.path.join(dirpath, thefile), "wb").write(templatize(src)) - if verbose: - sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) - cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % ( - domain, os.path.join(dirpath, thefile)) - (stdin, stdout, stderr) = os.popen3(cmd, 't') - msgs = stdout.read() - errors = stderr.read() - if errors: - print "errors happened while running xgettext on %s" % file - print errors - sys.exit(8) - if thefile != file: - old = '#: '+os.path.join(dirpath, thefile)[2:] - new = '#: '+os.path.join(dirpath, file)[2:] - msgs = msgs.replace(old, new) - if os.path.exists(potfile): - # Strip the header - msgs = '\n'.join(dropwhile(len, msgs.split('\n'))) - else: - msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8') - if msgs: - open(potfile, 'ab').write(msgs) - if thefile != file: - os.unlink(os.path.join(dirpath, thefile)) if os.path.exists(potfile): (stdin, stdout, stderr) = os.popen3('msguniq --to-code=utf-8 "%s"' % potfile, 'b') diff --git a/django/conf/locale/de/LC_MESSAGES/django.mo b/django/conf/locale/de/LC_MESSAGES/django.mo index 307976e4d5bb511b296973f9108c7405e7833a27..2699d25e55a01134e563a18e504413303fb119d9 100644 GIT binary patch delta 11754 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

jpjLPi`s3^jx&DhOWTj%Ib3LlVkFg-0!eG3E zYWEN3K<_zr2}4l>jz%39hl!Yk#V`e%;7%-uUUThD9g6{+-&Cfc5!FR?&=fV3o~Uay z7&Y=KE}x5C$yZ|pW}Ro-MWWipIcs5e@+R06x8MPMj5^<*6xP2Cg~Jpyv-_wH{zg4+ z-t+BEl+~FN^%UgCdKihirrod)&c&Yi94lgv1>Bgp7|Y{BXR(F$ac#Sh>tB`~{i%q= zrC0&eumRpfeObgWvP;(wb=NP$Mz|L{qt9adb=wsq$!DMjuo2b&6BT<)bB@V$Ys1+%? z%>KDP12w_xSPFA_mfM@8wzE4{X2*2Y$PZu%yoVY{?)U9~q^^R=x~n&%?uk99{YSACp2m_GwbIVCDXO1+ zs1^7Eb^JL@z-y?xKi?|*G&R97dj307(A{|+hhmWrY)6YxGg^r{@n%=Q1HH-jV>BK{ zFT9PRco%i;&1(A{5ry`}L@$+=U_dCHmtJs1w~l_5T1hz-Orbyw=-#zx7;yEm=+~G@^p2k(R|g7>{~P znxi`GiRx&ub2w^-V^AGWLQP;A2H-;H3Rk}Y)o!PAuZMy<*pL2r40WQ@r~zHZ0Q?Pg zGo_>U2XC+zaF%i=I1`<%oSmI-qWXIqHBirZw_`SHC6=OoO0C0^cnC8FfLii&)C~MK z+La1Kbrgy^J`&ZwEM{DL%((Wb2{u68Q!SC>JfcG7& zKZqGChPsqm4a@z`j`cK5}DgAD)63 zLR2UA5O;~+iO*f*wWSXa(;8orQLBojqcz)EJd^>G+J#* z7Bil@lSE#kDUp-7!oK=MGs@aVJ8j16*cIAPf0S}Aw_oQs*NLN4lq7s82l77kqWmYZ zh^VYaY+BwL){-Sd)D%)W&TsP%o?!)YT=L{AZtgCGq^H!55U@ zU}qa*6y^QIo0PxDz68G|%qPU##2(@tb?0#cQI7K8c!>z0Toy+Wug@YrbPf06RPxNN8+n@BmsuyhxOe=i@8>EbDR-ir=YQIEB7dUm zpSgWU#Us}!2+y(OVdhSpPOK%m5rMAVY0BAMIo5fbx=)E$$roV&(VlWN@xrwkM%_o0 zBXs^}B)^cvVPkw3eBi{FA_t*g_!z9Z3t`n|;Wlz(>n#J9w3>hBS?DHkKg zP;Q0V!YS{w#f;C7$>aacJ?1Bp1H^Q86ePM3Gs!pLV{C{Au_aN0&{l=I8@6bMQSLxF zk@!sYLShwjlot}(ek89& zY@&RRXh^(GJ_BDTzNGBUQ=n}f<<{6$?FntGFv69W=_J}-aush%cd&lh_>f<6`_!%` zkw9dj%}><-Of)8chuB6OCSOj>ATqZ@lrIy15m$-1ZpTQpU0q>+ufScSZ>Yip{k@cfOTXA(_iy5CU z^BF^31!5ZI$;2;2UP9X;OU7pzKK7_KCy1ex*Ane0zlRU-J3{~ODF6O{+fM06mrbMHUz9hy`~Z0v zk(C3U==u*LNhaF62H#SyNO>UM#fijO;(g*iv77o&i5tCLV-NZ`b0`b3FD;l1nGK8p4c@kd0+QdA{*)VhSb>+IQVjTHZ zSMHzL2tS~{D1OcP%`B3xIEH9Vc_3zz3aU=F7{FwOyyiS~, YEAR. +# Translation of django.po to German +# +# Copyright (C) 2005-2007, +# This file is distributed under the same license as the django package. # msgid "" "" @@ -1629,76 +1630,76 @@ msgstr "Webseite" msgid "flat pages" msgstr "Webseiten" -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "th" -msgstr "" +msgstr "." -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "st" -msgstr "" +msgstr "." -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "nd" -msgstr "" +msgstr "." -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "rd" -msgstr "" - -#: contrib/humanize/templatetags/humanize.py:47 -#, python-format -msgid "%(value).1f million" -msgid_plural "%(value).1f million" -msgstr[0] "" -msgstr[1] "" +msgstr "." #: contrib/humanize/templatetags/humanize.py:50 #, python-format -msgid "%(value).1f billion" -msgid_plural "%(value).1f billion" -msgstr[0] "" -msgstr[1] "" +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f Million" +msgstr[1] "%(value).1f Millionen" #: contrib/humanize/templatetags/humanize.py:53 #, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f Milliarde" +msgstr[1] "%(value).1f Milliarden" + +#: contrib/humanize/templatetags/humanize.py:56 +#, python-format msgid "%(value).1f trillion" msgid_plural "%(value).1f trillion" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(value).1f Billion" +msgstr[1] "%(value).1f Billionen" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "one" msgstr "ein" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "two" msgstr "zwei" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "three" msgstr "drei" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "four" msgstr "vier" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "five" msgstr "fünf" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "six" msgstr "sechs" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "seven" msgstr "sieben" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "eight" msgstr "acht" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "nine" msgstr "neun" diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py index be6cfede11..f79929e2d2 100644 --- a/django/contrib/auth/backends.py +++ b/django/contrib/auth/backends.py @@ -1,6 +1,11 @@ from django.db import connection from django.contrib.auth.models import User +try: + set +except NameError: + from sets import Set as set # Python 2.3 fallback + class ModelBackend: """ Authenticate against django.contrib.auth.models.User diff --git a/django/contrib/sessions/models.py b/django/contrib/sessions/models.py index c086396947..8fc5e17d69 100644 --- a/django/contrib/sessions/models.py +++ b/django/contrib/sessions/models.py @@ -1,5 +1,12 @@ -import base64, md5, random, sys, datetime +import os +import sys +import time +import datetime +import base64 +import md5 +import random import cPickle as pickle + from django.db import models from django.utils.translation import ugettext_lazy as _ from django.conf import settings diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py index 6fe24f5d13..16d1d822e0 100644 --- a/django/core/handlers/wsgi.py +++ b/django/core/handlers/wsgi.py @@ -1,16 +1,16 @@ +from threading import Lock +from pprint import pformat +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + from django.core.handlers.base import BaseHandler from django.core import signals from django.dispatch import dispatcher from django.utils import datastructures from django.utils.encoding import force_unicode from django import http -from pprint import pformat -from shutil import copyfileobj -from threading import Lock -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html STATUS_CODE_TEXT = { @@ -105,7 +105,8 @@ class WSGIRequest(http.HttpRequest): return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '') def is_secure(self): - return 'HTTPS' in self.environ and self.environ['HTTPS'] == 'on' + return 'wsgi.url_scheme' in self.environ \ + and self.environ['wsgi.url_scheme'] == 'https' def _load_post_and_files(self): # Populates self._post and self._files diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py index e15dfccdf2..cd90fd6109 100644 --- a/django/core/management/__init__.py +++ b/django/core/management/__init__.py @@ -239,7 +239,7 @@ def setup_environ(settings_mod): project_directory, settings_filename = os.path.split(settings_mod.__file__) project_name = os.path.basename(project_directory) settings_name = os.path.splitext(settings_filename)[0] - sys.path.append(os.path.join(project_directory, '..')) + sys.path.append(os.path.join(project_directory, os.pardir)) project_module = __import__(project_name, {}, {}, ['']) sys.path.pop() diff --git a/django/core/management/commands/startapp.py b/django/core/management/commands/startapp.py index 1da2776cf5..c238e74a08 100644 --- a/django/core/management/commands/startapp.py +++ b/django/core/management/commands/startapp.py @@ -16,7 +16,7 @@ class Command(LabelCommand): directory = os.getcwd() # Determine the project_name a bit naively -- by looking at the name of # the parent directory. - project_dir = os.path.normpath(os.path.join(directory, '..')) + project_dir = os.path.normpath(os.path.join(directory, os.pardir)) parent_dir = os.path.basename(project_dir) project_name = os.path.basename(directory) if app_name == project_name: diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 67f14f9baf..017f82a28b 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -236,7 +236,7 @@ class Field(object): if self.default is not NOT_PROVIDED: if callable(self.default): return self.default() - return self.default + return force_unicode(self.default, strings_only=True) if not self.empty_strings_allowed or (self.null and settings.DATABASE_ENGINE != 'oracle'): return None return "" diff --git a/django/http/__init__.py b/django/http/__init__.py index 9a47e70592..508c6d2f3e 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -47,8 +47,9 @@ class HttpRequest(object): def get_host(self): "Returns the HTTP host using the environment or request headers." # We try three options, in order of decreasing preference. - host = self.META.get('HTTP_X_FORWARDED_HOST', '') - if 'HTTP_HOST' in self.META: + if 'HTTP_X_FORWARDED_HOST' in self.META: + host = self.META['HTTP_X_FORWARDED_HOST'] + elif 'HTTP_HOST' in self.META: host = self.META['HTTP_HOST'] else: # Reconstruct the host using the algorithm from PEP 333. diff --git a/django/newforms/widgets.py b/django/newforms/widgets.py index eb67385e53..1336a20991 100644 --- a/django/newforms/widgets.py +++ b/django/newforms/widgets.py @@ -7,6 +7,7 @@ try: except NameError: from sets import Set as set # Python 2.3 fallback +import copy from itertools import chain from django.conf import settings from django.utils.datastructures import MultiValueDict @@ -135,6 +136,12 @@ class Widget(object): else: self.attrs = {} + def __deepcopy__(self, memo): + obj = copy.copy(self) + obj.attrs = self.attrs.copy() + memo[id(self)] = obj + return obj + def render(self, name, value, attrs=None): """ Returns this Widget rendered as HTML, as a Unicode string. @@ -191,7 +198,7 @@ class PasswordInput(Input): input_type = 'password' def __init__(self, attrs=None, render_value=True): - self.attrs = attrs or {} + super(PasswordInput, self).__init__(attrs) self.render_value = render_value def render(self, name, value, attrs=None): @@ -208,8 +215,8 @@ class MultipleHiddenInput(HiddenInput): of values. """ def __init__(self, attrs=None, choices=()): + super(MultipleHiddenInput, self).__init__(attrs) # choices can be any iterable - self.attrs = attrs or {} self.choices = choices def render(self, name, value, attrs=None, choices=()): @@ -248,9 +255,9 @@ class Textarea(Widget): class CheckboxInput(Widget): def __init__(self, attrs=None, check_test=bool): + super(CheckboxInput, self).__init__(attrs) # check_test is a callable that takes a value and returns True # if the checkbox should be checked for that value. - self.attrs = attrs or {} self.check_test = check_test def render(self, name, value, attrs=None): @@ -267,7 +274,7 @@ class CheckboxInput(Widget): class Select(Widget): def __init__(self, attrs=None, choices=()): - self.attrs = attrs or {} + super(Select, self).__init__(attrs) # choices can be any iterable, but we may need to render this widget # multiple times. Thus, collapse it into a list so it can be consumed # more than once. @@ -306,8 +313,8 @@ class NullBooleanSelect(Select): class SelectMultiple(Widget): def __init__(self, attrs=None, choices=()): + super(SelectMultiple, self).__init__(attrs) # choices can be any iterable - self.attrs = attrs or {} self.choices = choices def render(self, name, value, attrs=None, choices=()): @@ -530,4 +537,3 @@ class SplitDateTimeWidget(MultiWidget): if value: return [value.date(), value.time()] return [None, None] - \ No newline at end of file diff --git a/django/oldforms/__init__.py b/django/oldforms/__init__.py index 9bb90416c4..5f7b9fc2ad 100644 --- a/django/oldforms/__init__.py +++ b/django/oldforms/__init__.py @@ -500,7 +500,7 @@ class SelectField(FormField): selected_html = u'' if smart_unicode(value) == str_data: selected_html = u' selected="selected"' - output.append(u' ' % (escape(value), selected_html, escape(display_name))) + output.append(u' ' % (escape(value), selected_html, force_unicode(escape(display_name)))) output.append(u' ') return u'\n'.join(output) @@ -612,7 +612,7 @@ class SelectMultipleField(SelectField): selected_html = u'' if smart_unicode(value) in str_data_list: selected_html = u' selected="selected"' - output.append(u' ' % (escape(value), selected_html, escape(choice))) + output.append(u' ' % (escape(value), selected_html, force_unicode(escape(choice)))) output.append(u' ') return u'\n'.join(output) diff --git a/django/utils/cache.py b/django/utils/cache.py index 2494d7839e..f192e1115c 100644 --- a/django/utils/cache.py +++ b/django/utils/cache.py @@ -23,7 +23,7 @@ import time from email.Utils import formatdate from django.conf import settings from django.core.cache import cache -from django.utils.encoding import smart_str +from django.utils.encoding import smart_str, iri_to_uri cc_delim_re = re.compile(r'\s*,\s*') @@ -57,6 +57,13 @@ def patch_cache_control(response, **kwargs): cc = dict([dictitem(el) for el in cc]) else: cc = {} + + # If there's already a max-age header but we're being asked to set a new + # max-age, use the minumum of the two ages. In practice this happens when + # a decorator and a piece of middleware both operate on a given view. + if 'max-age' in cc and 'max_age' in kwargs: + kwargs['max_age'] = min(cc['max-age'], kwargs['max_age']) + for (k,v) in kwargs.items(): cc[k.replace('_', '-')] = v cc = ', '.join([dictvalue(el) for el in cc.items()]) @@ -118,7 +125,7 @@ def _generate_cache_key(request, headerlist, key_prefix): value = request.META.get(header, None) if value is not None: ctx.update(value) - return 'views.decorators.cache.cache_page.%s.%s.%s' % (key_prefix, request.path, ctx.hexdigest()) + return 'views.decorators.cache.cache_page.%s.%s.%s' % (key_prefix, iri_to_uri(request.path), ctx.hexdigest()) def get_cache_key(request, key_prefix=None): """ @@ -132,7 +139,7 @@ def get_cache_key(request, key_prefix=None): """ if key_prefix is None: key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX - cache_key = 'views.decorators.cache.cache_header.%s.%s' % (key_prefix, request.path) + cache_key = 'views.decorators.cache.cache_header.%s.%s' % (key_prefix, iri_to_uri(request.path)) headerlist = cache.get(cache_key, None) if headerlist is not None: return _generate_cache_key(request, headerlist, key_prefix) @@ -156,7 +163,7 @@ def learn_cache_key(request, response, cache_timeout=None, key_prefix=None): key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX if cache_timeout is None: cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS - cache_key = 'views.decorators.cache.cache_header.%s.%s' % (key_prefix, request.path) + cache_key = 'views.decorators.cache.cache_header.%s.%s' % (key_prefix, iri_to_uri(request.path)) if response.has_header('Vary'): headerlist = ['HTTP_'+header.upper().replace('-', '_') for header in vary_delim_re.split(response['Vary'])] cache.set(cache_key, headerlist, cache_timeout) diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py index 13fc8a847a..9ca7419e1e 100644 --- a/django/utils/translation/__init__.py +++ b/django/utils/translation/__init__.py @@ -2,6 +2,7 @@ Internationalization support. """ from django.utils.functional import lazy +from django.utils.encoding import force_unicode __all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext', 'ngettext_lazy', 'string_concat', 'activate', 'deactivate', @@ -39,7 +40,7 @@ def delayed_loader(*args, **kwargs): g['real_%s' % name] = getattr(trans, name) # Make the originally requested function call on the way out the door. - return g[caller](*args, **kwargs) + return g['real_%s' % caller](*args, **kwargs) g = globals() for name in __all__: @@ -63,14 +64,10 @@ def ugettext(message): def ungettext(singular, plural, number): return real_ungettext(singular, plural, number) -def string_concat(*strings): - return real_string_concat(*strings) - ngettext_lazy = lazy(ngettext, str) gettext_lazy = lazy(gettext, str) ungettext_lazy = lazy(ungettext, unicode) ugettext_lazy = lazy(ugettext, unicode) -string_concat = lazy(string_concat, unicode) def activate(language): return real_activate(language) @@ -108,3 +105,10 @@ def templatize(src): def deactivate_all(): return real_deactivate_all() +def string_concat(*strings): + """ + Lazy variant of string concatenation, needed for translations that are + constructed from multiple parts. + """ + return u''.join([force_unicode(s) for s in strings]) +string_concat = lazy(string_concat, unicode) diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py index e3f89567a5..771a80e99c 100644 --- a/django/utils/translation/trans_null.py +++ b/django/utils/translation/trans_null.py @@ -13,7 +13,6 @@ ngettext_lazy = ngettext def ungettext(singular, plural, number): return force_unicode(ngettext(singular, plural, number)) -string_concat = lambda *strings: u''.join([force_unicode(el) for el in strings]) activate = lambda x: None deactivate = deactivate_all = install = lambda: None get_language = lambda: settings.LANGUAGE_CODE diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index 5fff1ea63a..250af04e8c 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -516,9 +516,3 @@ def templatize(src): out.write(blankout(t.contents, 'X')) return out.getvalue() -def string_concat(*strings): - """" - Lazy variant of string concatenation, needed for translations that are - constructed from multiple parts. - """ - return u''.join([force_unicode(s) for s in strings]) diff --git a/django/views/static.py b/django/views/static.py index 3ec4ca14a1..e274057617 100644 --- a/django/views/static.py +++ b/django/views/static.py @@ -29,12 +29,12 @@ def serve(request, path, document_root=None, show_indexes=False): newpath = '' for part in path.split('/'): if not part: - # strip empty path components + # Strip empty path components. continue drive, part = os.path.splitdrive(part) head, part = os.path.split(part) if part in (os.curdir, os.pardir): - # strip '.' amd '..' in path + # Strip '.' and '..' in path. continue newpath = os.path.join(newpath, part).replace('\\', '/') if newpath and path != newpath: diff --git a/docs/databases.txt b/docs/databases.txt index 21ff4c7434..213c2d666c 100644 --- a/docs/databases.txt +++ b/docs/databases.txt @@ -163,3 +163,118 @@ storage engine, you have a couple of options. .. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB + +Oracle Notes +============ + +Django supports `Oracle Database Server`_ versions 9i and higher. Oracle +version 10g or later is required to use Django's ``regex`` and ``iregex`` query +operators. You will also need the `cx_Oracle`_ driver, version 4.3.1 or newer. + +.. _`Oracle Database Server`: http://www.oracle.com/ +.. _`cx_Oracle`: http://cx-oracle.sourceforge.net/ + +To run ``python manage.py syncdb``, you'll need to create an Oracle database +user with CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE, and CREATE TRIGGER +privileges. To run Django's test suite, the user also needs +CREATE and DROP DATABASE and CREATE and DROP TABLESPACE privileges. + +Connecting to the Database +-------------------------- + +Your Django settings.py file should look something like this for Oracle:: + + DATABASE_ENGINE = 'oracle' + DATABASE_NAME = 'xe' + DATABASE_USER = 'a_user' + DATABASE_PASSWORD = 'a_password' + DATABASE_HOST = '' + DATABASE_PORT = '' + +If you don't use a ``tnsnames.ora`` file or a similar naming method that +recognizes the SID ("xe" in this example), then fill in both ``DATABASE_HOST`` +and ``DATABASE_PORT`` like so:: + + DATABASE_ENGINE = 'oracle' + DATABASE_NAME = 'xe' + DATABASE_USER = 'a_user' + DATABASE_PASSWORD = 'a_password' + DATABASE_HOST = 'dbprod01ned.mycompany.com' + DATABASE_PORT = '1540' + +You should supply both ``DATABASE_HOST`` and ``DATABASE_PORT``, or leave both +as empty strings. + +Tablespace Options +------------------ + +A common paradigm for optimizing performance in Oracle-based systems is the +use of `tablespaces`_ to organize disk layout. The Oracle backend supports +this use case by adding ``db_tablespace`` options to the ``Meta`` and +``Field`` classes. (When using a backend that lacks support for tablespaces, +these options are ignored.) + +.. _`tablespaces`: http://en.wikipedia.org/wiki/Tablespace + +A tablespace can be specified for the table(s) generated by a model by +supplying the ``db_tablespace`` option inside the model's ``Meta`` class. +Additionally, the ``db_tablespace`` option can be passed to a ``Field`` +constructor to specify an alternate tablespace for the ``Field``'s column +index. If no index would be created for the column, the ``db_tablespace`` +option is ignored. + +:: + + class TablespaceExample(models.Model): + name = models.CharField(maxlength=30, db_index=True, db_tablespace="indexes") + data = models.CharField(maxlength=255, db_index=True) + edges = models.ManyToManyField(to="self", db_tablespace="indexes") + + class Meta: + db_tablespace = "tables" + +In this example, the tables generated by the ``TablespaceExample`` model +(i.e., the model table and the many-to-many table) would be stored in the +``tables`` tablespace. The index for the name field and the indexes on the +many-to-many table would be stored in the ``indexes`` tablespace. The ``data`` +field would also generate an index, but no tablespace for it is specified, so +it would be stored in the model tablespace ``tables`` by default. + +Django does not create the tablespaces for you. Please refer to `Oracle's +documentation`_ for details on creating and managing tablespaces. + +.. _`Oracle's documentation`: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7003.htm#SQLRF01403 + +Naming Issues +------------- + +Oracle imposes a name length limit of 30 characters. To accommodate this, the +backend truncates database identifiers to fit, replacing the final four +characters of the truncated name with a repeatable MD5 hash value. + +NULL and Empty Strings +---------------------- + +Django generally prefers to use the empty string ('') rather than NULL, but +Oracle treats both identically. To get around this, the Oracle backend +coerces the ``null=True`` option on fields that permit the empty string as a +value. When fetching from the database, it is assumed that a NULL value in +one of these fields really means the empty string, and the data is silently +converted to reflect this assumption. + +TextField Limitations +--------------------- + +The Oracle backend stores ``TextFields`` as ``NCLOB`` columns. Oracle imposes +some limitations on the usage of such LOB columns in general: + + * LOB columns may not be used as primary keys. + + * LOB columns may not be used in indexes. + + * LOB columns may not be used in a ``SELECT DISTINCT`` list. This means that + attempting to use the ``QuerySet.distinct`` method on a model that + includes ``TextField`` columns will result in an error when run against + Oracle. A workaround to this is to keep ``TextField`` columns out of any + models that you foresee performing ``.distinct`` queries on, and to + include the ``TextField`` in a related model instead. diff --git a/docs/email.txt b/docs/email.txt index 2bad79ce33..effc5e24cf 100644 --- a/docs/email.txt +++ b/docs/email.txt @@ -317,7 +317,7 @@ To send a text and HTML combination, you could write:: subject, from_email, to = 'hello', 'from@example.com', 'to@example.com' text_content = 'This is an important message.' html_content = '

This is an important message.

' - msg = EmailMultiAlternatives(subject, text_content, from_email, to) + msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send() diff --git a/docs/install.txt b/docs/install.txt index 2de8529d24..95aa82b2e3 100644 --- a/docs/install.txt +++ b/docs/install.txt @@ -66,6 +66,7 @@ installed. * If you're using SQLite, you'll need pysqlite_. Use version 2.0.3 or higher. * If you're using Oracle, you'll need cx_Oracle_, version 4.3.1 or higher. + You will also want to read the database-specific notes for the `Oracle backend`_. If you plan to use Django's ``manage.py syncdb`` command to automatically create database tables for your models, you'll need to @@ -88,6 +89,7 @@ to create a temporary test database. .. _MySQL backend: ../databases/ .. _cx_Oracle: http://cx-oracle.sourceforge.net/ .. _Oracle: http://www.oracle.com/ +.. _Oracle backend: ../databases/#oracle-notes .. _testing framework: ../testing/ Remove any old versions of Django diff --git a/docs/newforms.txt b/docs/newforms.txt index 54bd6306c7..531c4fbb36 100644 --- a/docs/newforms.txt +++ b/docs/newforms.txt @@ -2388,9 +2388,9 @@ More coming soon ================ That's all the documentation for now. For more, see the file -http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/forms/tests.py +http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/forms -- the unit tests for ``django.newforms``. This can give you a good idea of -what's possible. +what's possible. (Each submodule there contains separate tests.) If you're really itching to learn and use this library, please be patient. We're working hard on finishing both the code and documentation. diff --git a/tests/modeltests/basic/models.py b/tests/modeltests/basic/models.py index 58770ef2ce..2f4b932fe0 100644 --- a/tests/modeltests/basic/models.py +++ b/tests/modeltests/basic/models.py @@ -152,7 +152,7 @@ TypeError: 'foo' is an invalid keyword argument for this function >>> a6 = Article(pub_date=datetime(2005, 7, 31)) >>> a6.save() >>> a6.headline -'Default headline' +u'Default headline' # For DateTimeFields, Django saves as much precision (in seconds) as you # give it. diff --git a/tests/modeltests/field_defaults/models.py b/tests/modeltests/field_defaults/models.py index 23c4733b8f..1132f1ca41 100644 --- a/tests/modeltests/field_defaults/models.py +++ b/tests/modeltests/field_defaults/models.py @@ -42,7 +42,7 @@ __test__ = {'API_TESTS':""" # Access database columns via Python attributes. >>> a.headline -'Default headline' +u'Default headline' # make sure the two dates are sufficiently close >>> d = now - a.pub_date diff --git a/tests/regressiontests/i18n/models.py b/tests/regressiontests/i18n/models.py index e69de29bb2..e1eefb8477 100644 --- a/tests/regressiontests/i18n/models.py +++ b/tests/regressiontests/i18n/models.py @@ -0,0 +1,12 @@ +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +class TestModel(models.Model): + text = models.CharField(max_length=10, default=_('Anything')) + +__test__ = {'API_TESTS': ''' +>>> tm = TestModel() +>>> tm.save() +''' +} + diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py index 8a7d2bee3e..99204451e4 100644 --- a/tests/regressiontests/i18n/tests.py +++ b/tests/regressiontests/i18n/tests.py @@ -30,4 +30,12 @@ True >>> s4 = ugettext_lazy('Some other string') >>> s == s4 False + +unicode(string_concat(...)) should not raise a TypeError - #4796 + +>>> import django.utils.translation +>>> reload(django.utils.translation) + +>>> unicode(django.utils.translation.string_concat("dja", "ngo")) +u'django' """