1
0
mirror of https://github.com/django/django.git synced 2025-07-04 01:39:20 +00:00

newforms-admin: Merged to [6458]

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@6459 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Joseph Kocherhans 2007-10-06 22:34:48 +00:00
parent 4e3eb6ed5f
commit 6104f6bd85
27 changed files with 294 additions and 126 deletions

View File

@ -115,6 +115,7 @@ answer newbie questions, and generally made Django that much better:
Enrico <rico.bl@gmail.com>
A. Murat Eren <meren@pardus.org.tr>
Ludvig Ericson <ludvig.ericson@gmail.com>
eriks@win.tue.nl
Dirk Eschler <dirk.eschler@gmx.net>
Marc Fargas <telenieko@telenieko.com>
Szilveszter Farkas <szilveszter.farkas@gmail.com>
@ -239,6 +240,7 @@ answer newbie questions, and generally made Django that much better:
Jay Parlar <parlar@gmail.com>
pavithran s <pavithran.s@gmail.com>
Barry Pederson <bp@barryp.org>
permonik@mesias.brnonet.cz
petr.marhoun@gmail.com
pgross@thoughtworks.com
phaedo <http://phaedo.cx/>
@ -317,7 +319,7 @@ answer newbie questions, and generally made Django that much better:
Vlado <vlado@labath.org>
Milton Waddams
wam-djangobug@wamber.net
wangchun <yaohua2000@gmail.com>
Wang Chun <wangchun@exoweb.net>
Filip Wasilewski <filip.wasilewski@gmail.com>
Dan Watson <http://theidioteque.net/>
Chris Wesseling <Chris.Wesseling@cwi.nl>

View File

@ -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)))

View File

@ -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')

View File

@ -1,6 +1,7 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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:

View File

@ -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 ""

View File

@ -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.

View File

@ -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]

View File

@ -500,7 +500,7 @@ class SelectField(FormField):
selected_html = u''
if smart_unicode(value) == str_data:
selected_html = u' selected="selected"'
output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(display_name)))
output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, force_unicode(escape(display_name))))
output.append(u' </select>')
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' <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(choice)))
output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, force_unicode(escape(choice))))
output.append(u' </select>')
return u'\n'.join(output)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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])

View File

@ -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:

View File

@ -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.

View File

@ -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 = '<p>This is an <strong>important</strong> message.</p>'
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()

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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()
'''
}

View File

@ -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)
<module 'django.utils.translation' from ...>
>>> unicode(django.utils.translation.string_concat("dja", "ngo"))
u'django'
"""