mirror of
https://github.com/django/django.git
synced 2025-07-03 17:29:12 +00:00
unicode: Merged changes from trunk up to [5460].
git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5462 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
0b4122d138
commit
748ea65a61
4
AUTHORS
4
AUTHORS
@ -73,6 +73,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Michal Chruszcz <troll@pld-linux.org>
|
||||
Ian Clelland <clelland@gmail.com>
|
||||
crankycoder@gmail.com
|
||||
Pete Crosier <pete.crosier@gmail.com>
|
||||
Matt Croydon <http://www.postneo.com/>
|
||||
flavio.curella@gmail.com
|
||||
Jure Cuhalev <gandalf@owca.info>
|
||||
@ -131,6 +132,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
junzhang.jn@gmail.com
|
||||
Antti Kaihola <http://akaihola.blogspot.com/>
|
||||
Ben Dean Kawamura <ben.dean.kawamura@gmail.com>
|
||||
ian.g.kelly@gmail.com
|
||||
Garth Kidd <http://www.deadlybloodyserious.com/>
|
||||
kilian <kilian.cavalotti@lip6.fr>
|
||||
Sune Kirkeby <http://ibofobi.dk/>
|
||||
@ -171,6 +173,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
mitakummaa@gmail.com
|
||||
mmarshall
|
||||
Eric Moritz <http://eric.themoritzfamily.com/>
|
||||
mrmachine <real.human@mrmachine.net>
|
||||
Robin Munn <http://www.geekforgod.com/>
|
||||
Robert Myers <myer0052@gmail.com>
|
||||
Nebojša Dorđević
|
||||
@ -236,6 +239,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
wangchun <yaohua2000@gmail.com>
|
||||
Dan Watson <http://theidioteque.net/>
|
||||
Chris Wesseling <Chris.Wesseling@cwi.nl>
|
||||
James Wheare <django@sparemint.com>
|
||||
charly.wilhelm@gmail.com
|
||||
Rachel Willmer <http://www.willmer.com/kb/>
|
||||
Gary Wilson <gary.wilson@gmail.com>
|
||||
|
@ -1 +1,8 @@
|
||||
VERSION = (0, 97, 'pre')
|
||||
|
||||
def get_version():
|
||||
"Returns the version as a human-format string."
|
||||
v = '.'.join([str(i) for i in VERSION[:-1]])
|
||||
if VERSION[-1]:
|
||||
v += '-' + VERSION[-1]
|
||||
return v
|
||||
|
@ -244,7 +244,8 @@ TRANSACTIONS_MANAGED = False
|
||||
|
||||
# The User-Agent string to use when checking for URL validity through the
|
||||
# isExistingURL validator.
|
||||
URL_VALIDATOR_USER_AGENT = "Django/0.96pre (http://www.djangoproject.com)"
|
||||
from django import get_version
|
||||
URL_VALIDATOR_USER_AGENT = "Django/%s (http://www.djangoproject.com)" % get_version()
|
||||
|
||||
##############
|
||||
# MIDDLEWARE #
|
||||
|
Binary file not shown.
@ -2202,10 +2202,11 @@ msgstr[0] "dag"
|
||||
msgstr[1] "dagen"
|
||||
|
||||
#: utils/timesince.py:16
|
||||
# In the timesince context it is stilistically wrong to use the plural for hour in Dutch.
|
||||
msgid "hour"
|
||||
msgid_plural "hours"
|
||||
msgstr[0] "uur"
|
||||
msgstr[1] "uren"
|
||||
msgstr[1] "uur"
|
||||
|
||||
#: utils/timesince.py:17
|
||||
msgid "minute"
|
||||
|
@ -3,14 +3,17 @@
|
||||
|
||||
import django
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
import os, re, shutil, sys, textwrap
|
||||
from optparse import OptionParser
|
||||
from django.utils import termcolors
|
||||
import os, re, shutil, sys, textwrap
|
||||
|
||||
# For Python 2.3
|
||||
if not hasattr(__builtins__, 'set'):
|
||||
from sets import Set as set
|
||||
|
||||
# For backwards compatibility: get_version() used to be in this module.
|
||||
get_version = django.get_version
|
||||
|
||||
MODULE_TEMPLATE = ''' {%% if perms.%(app)s.%(addperm)s or perms.%(app)s.%(changeperm)s %%}
|
||||
<tr>
|
||||
<th>{%% if perms.%(app)s.%(changeperm)s %%}<a href="%(app)s/%(mod)s/">{%% endif %%}%(name)s{%% if perms.%(app)s.%(changeperm)s %%}</a>{%% endif %%}</th>
|
||||
@ -93,14 +96,6 @@ def _get_sequence_list():
|
||||
# field as the field to which it points.
|
||||
get_rel_data_type = lambda f: (f.get_internal_type() in ('AutoField', 'PositiveIntegerField', 'PositiveSmallIntegerField')) and 'IntegerField' or f.get_internal_type()
|
||||
|
||||
def get_version():
|
||||
"Returns the version as a human-format string."
|
||||
from django import VERSION
|
||||
v = '.'.join([str(i) for i in VERSION[:-1]])
|
||||
if VERSION[-1]:
|
||||
v += '-' + VERSION[-1]
|
||||
return v
|
||||
|
||||
def get_sql_create(app):
|
||||
"Returns a list of the CREATE TABLE SQL statements for the given app."
|
||||
from django.db import get_creation_module, models
|
||||
|
@ -239,22 +239,27 @@ def get_sql_sequence_reset(style, model_list):
|
||||
from django.db import models
|
||||
output = []
|
||||
for model in model_list:
|
||||
# Use `coalesce` to set the sequence for each model to the max pk value if there are records,
|
||||
# or 1 if there are none. Set the `is_called` property (the third argument to `setval`) to true
|
||||
# if there are records (as the max pk value is already in use), otherwise set it to false.
|
||||
for f in model._meta.fields:
|
||||
if isinstance(f, models.AutoField):
|
||||
output.append("%s setval('%s', (%s max(%s) %s %s));" % \
|
||||
output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \
|
||||
(style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD(quote_name('%s_%s_seq' % (model._meta.db_table, f.column))),
|
||||
style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD(quote_name(f.column)),
|
||||
style.SQL_FIELD(quote_name(f.column)),
|
||||
style.SQL_KEYWORD('IS NOT'),
|
||||
style.SQL_KEYWORD('FROM'),
|
||||
style.SQL_TABLE(quote_name(model._meta.db_table))))
|
||||
break # Only one AutoField is allowed per model, so don't bother continuing.
|
||||
for f in model._meta.many_to_many:
|
||||
output.append("%s setval('%s', (%s max(%s) %s %s));" % \
|
||||
output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \
|
||||
(style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD(quote_name('%s_id_seq' % f.m2m_db_table())),
|
||||
style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD(quote_name('id')),
|
||||
style.SQL_FIELD(quote_name('id')),
|
||||
style.SQL_KEYWORD('IS NOT'),
|
||||
style.SQL_KEYWORD('FROM'),
|
||||
style.SQL_TABLE(f.m2m_db_table())))
|
||||
return output
|
||||
|
@ -180,22 +180,27 @@ def get_sql_sequence_reset(style, model_list):
|
||||
from django.db import models
|
||||
output = []
|
||||
for model in model_list:
|
||||
# Use `coalesce` to set the sequence for each model to the max pk value if there are records,
|
||||
# or 1 if there are none. Set the `is_called` property (the third argument to `setval`) to true
|
||||
# if there are records (as the max pk value is already in use), otherwise set it to false.
|
||||
for f in model._meta.fields:
|
||||
if isinstance(f, models.AutoField):
|
||||
output.append("%s setval('%s', (%s max(%s) %s %s));" % \
|
||||
output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \
|
||||
(style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD(quote_name('%s_%s_seq' % (model._meta.db_table, f.column))),
|
||||
style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD(quote_name(f.column)),
|
||||
style.SQL_FIELD(quote_name(f.column)),
|
||||
style.SQL_KEYWORD('IS NOT'),
|
||||
style.SQL_KEYWORD('FROM'),
|
||||
style.SQL_TABLE(quote_name(model._meta.db_table))))
|
||||
break # Only one AutoField is allowed per model, so don't bother continuing.
|
||||
for f in model._meta.many_to_many:
|
||||
output.append("%s setval('%s', (%s max(%s) %s %s));" % \
|
||||
output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \
|
||||
(style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD(quote_name('%s_id_seq' % f.m2m_db_table())),
|
||||
style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD(quote_name('id')),
|
||||
style.SQL_FIELD(quote_name('id')),
|
||||
style.SQL_KEYWORD('IS NOT'),
|
||||
style.SQL_KEYWORD('FROM'),
|
||||
style.SQL_TABLE(f.m2m_db_table())))
|
||||
return output
|
||||
|
@ -98,7 +98,7 @@ def typecast_boolean(s):
|
||||
return str(s)[0].lower() == 't'
|
||||
|
||||
def typecast_decimal(s):
|
||||
if s is None:
|
||||
if s is None or s == '':
|
||||
return None
|
||||
return decimal.Decimal(s)
|
||||
|
||||
|
@ -8,6 +8,14 @@ from django.utils.encoding import smart_str, smart_unicode
|
||||
import sys
|
||||
import re
|
||||
|
||||
if not hasattr(__builtins__, 'reversed'):
|
||||
# For Python 2.3.
|
||||
# From http://www.python.org/doc/current/tut/node11.html
|
||||
def reversed(data):
|
||||
for index in xrange(len(data)-1, -1, -1):
|
||||
yield data[index]
|
||||
|
||||
|
||||
register = Library()
|
||||
|
||||
class CommentNode(Node):
|
||||
@ -104,11 +112,7 @@ class ForNode(Node):
|
||||
values = list(values)
|
||||
len_values = len(values)
|
||||
if self.reversed:
|
||||
# From http://www.python.org/doc/current/tut/node11.html
|
||||
def reverse(data):
|
||||
for index in range(len(data)-1, -1, -1):
|
||||
yield data[index]
|
||||
values = reverse(values)
|
||||
values = reversed(values)
|
||||
unpack = len(self.loopvars) > 1
|
||||
for i, item in enumerate(values):
|
||||
context['forloop'] = {
|
||||
|
@ -3,7 +3,7 @@ from django.template import Template, Context, TemplateDoesNotExist
|
||||
from django.utils.html import escape
|
||||
from django.http import HttpResponseServerError, HttpResponseNotFound
|
||||
from django.utils.encoding import smart_unicode
|
||||
import os, re
|
||||
import os, re, sys
|
||||
|
||||
HIDDEN_SETTINGS = re.compile('SECRET|PASSWORD|PROFANITIES_LIST')
|
||||
|
||||
@ -132,6 +132,8 @@ def technical_500_response(request, exc_type, exc_value, tb):
|
||||
'request': request,
|
||||
'request_protocol': request.is_secure() and "https" or "http",
|
||||
'settings': get_safe_settings(),
|
||||
'sys_executable' : sys.executable,
|
||||
'sys_version_info' : '%d.%d.%d' % sys.version_info[0:3],
|
||||
'template_info': template_info,
|
||||
'template_does_not_exist': template_does_not_exist,
|
||||
'loader_debug_info': loader_debug_info,
|
||||
@ -346,6 +348,14 @@ TECHNICAL_500_TEMPLATE = """
|
||||
<th>Exception Location:</th>
|
||||
<td>{{ lastframe.filename|escape }} in {{ lastframe.function|escape }}, line {{ lastframe.lineno }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Python Executable:</th>
|
||||
<td>{{ sys_executable|escape }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Python Version:</th>
|
||||
<td>{{ sys_version_info }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% if template_does_not_exist %}
|
||||
|
@ -730,7 +730,7 @@ Django developers are currently discussing.
|
||||
Default permissions
|
||||
-------------------
|
||||
|
||||
Three basic permissions -- add, create and delete -- are automatically created
|
||||
Three basic permissions -- add, change and delete -- are automatically created
|
||||
for each Django model that has a ``class Admin`` set. Behind the scenes, these
|
||||
permissions are added to the ``auth_permission`` database table when you run
|
||||
``manage.py syncdb``.
|
||||
|
@ -388,7 +388,7 @@ The lookup parameters (``**kwargs``) should be in the format described in
|
||||
`Field lookups`_ below. Multiple parameters are joined via ``AND`` in the
|
||||
underlying SQL statement, and the whole thing is enclosed in a ``NOT()``.
|
||||
|
||||
This example excludes all entries whose ``pub_date`` is the current date/time
|
||||
This example excludes all entries whose ``pub_date`` is later than 2005-1-3
|
||||
AND whose ``headline`` is "Hello"::
|
||||
|
||||
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')
|
||||
@ -398,8 +398,8 @@ In SQL terms, that evaluates to::
|
||||
SELECT ...
|
||||
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
|
||||
|
||||
This example excludes all entries whose ``pub_date`` is the current date/time
|
||||
OR whose ``headline`` is "Hello"::
|
||||
This example excludes all entries whose ``pub_date`` is later than 2005-1-3
|
||||
AND whose headline is NOT "Hello"::
|
||||
|
||||
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')
|
||||
|
||||
|
162
docs/man/django-admin.1
Normal file
162
docs/man/django-admin.1
Normal file
@ -0,0 +1,162 @@
|
||||
.TH "django-admin.py" "1" "June 2007" "Django Project" ""
|
||||
.SH "NAME"
|
||||
django\-admin.py \- Utility script for the Django web framework
|
||||
.SH "SYNOPSIS"
|
||||
.B django\-admin.py
|
||||
.I <action>
|
||||
.B [options]
|
||||
.sp
|
||||
.SH "DESCRIPTION"
|
||||
This utility script provides commands for creation and maintenance of Django
|
||||
projects and apps.
|
||||
.sp
|
||||
With the exception of
|
||||
.BI startproject,
|
||||
all commands listed below can also be performed with the
|
||||
.BI manage.py
|
||||
script found at the top level of each Django project directory.
|
||||
.sp
|
||||
.SH "ACTIONS"
|
||||
.TP
|
||||
.BI "adminindex [" "appname ..." "]"
|
||||
Prints the admin\-index template snippet for the given app name(s).
|
||||
.TP
|
||||
.BI "createcachetable [" "tablename" "]"
|
||||
Creates the table needed to use the SQL cache backend
|
||||
.TP
|
||||
.B dbshell
|
||||
Runs the command\-line client for the current
|
||||
.BI DATABASE_ENGINE.
|
||||
.TP
|
||||
.B diffsettings
|
||||
Displays differences between the current
|
||||
.B settings.py
|
||||
and Django's default settings. Settings that don't appear in the defaults are
|
||||
followed by "###".
|
||||
.TP
|
||||
.B inspectdb
|
||||
Introspects the database tables in the database specified in settings.py and outputs a Django
|
||||
model module.
|
||||
.TP
|
||||
.BI "install [" "appname ..." "]"
|
||||
Executes
|
||||
.B sqlall
|
||||
for the given app(s) in the current database.
|
||||
.TP
|
||||
.BI "reset [" "appname ..." "]"
|
||||
Executes
|
||||
.B sqlreset
|
||||
for the given app(s) in the current database.
|
||||
.TP
|
||||
.BI "runfcgi [" "KEY=val" "] [" "KEY=val" "] " "..."
|
||||
Runs this project as a FastCGI application. Requires flup. Use
|
||||
.B runfcgi help
|
||||
for help on the KEY=val pairs.
|
||||
.TP
|
||||
.BI "runserver [" "\-\-noreload" "] [" "\-\-adminmedia=ADMIN_MEDIA_PATH" "] [" "port|ipaddr:port" "]"
|
||||
Starts a lightweight Web server for development.
|
||||
.TP
|
||||
.BI "shell [" "\-\-plain" "]"
|
||||
Runs a Python interactive interpreter. Tries to use IPython, if it's available.
|
||||
The
|
||||
.BI \-\-plain
|
||||
option forces the use of the standard Python interpreter even when IPython is
|
||||
installed.
|
||||
.TP
|
||||
.BI "sql [" "appname ..." "]"
|
||||
Prints the CREATE TABLE SQL statements for the given app name(s).
|
||||
.TP
|
||||
.BI "sqlall [" "appname ..." "]"
|
||||
Prints the CREATE TABLE, initial\-data and CREATE INDEX SQL statements for the
|
||||
given model module name(s).
|
||||
.TP
|
||||
.BI "sqlclear [" "appname ..." "]"
|
||||
Prints the DROP TABLE SQL statements for the given app name(s).
|
||||
.TP
|
||||
.BI "sqlindexes [" "appname ..." "]"
|
||||
Prints the CREATE INDEX SQL statements for the given model module name(s).
|
||||
.TP
|
||||
.BI "sqlinitialdata [" "appname ..." "]"
|
||||
Prints the initial INSERT SQL statements for the given app name(s).
|
||||
.TP
|
||||
.BI "sqlreset [" "appname ..." "]"
|
||||
Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app
|
||||
name(s).
|
||||
.TP
|
||||
.BI "sqlsequencereset [" "appname ..." "]"
|
||||
Prints the SQL statements for resetting PostgreSQL sequences for the
|
||||
given app name(s).
|
||||
.TP
|
||||
.BI "startapp [" "appname" "]"
|
||||
Creates a Django app directory structure for the given app name in
|
||||
the current directory.
|
||||
.TP
|
||||
.BI "startproject [" "projectname" "]"
|
||||
Creates a Django project directory structure for the given project name
|
||||
in the current directory.
|
||||
.TP
|
||||
.BI syncdb
|
||||
Creates the database tables for all apps in INSTALLED_APPS whose tables
|
||||
haven't already been created.
|
||||
.TP
|
||||
.BI "test [" "\-\-verbosity" "] [" "appname ..." "]"
|
||||
Runs the test suite for the specified applications, or the entire project if
|
||||
no apps are specified
|
||||
.TP
|
||||
.BI validate
|
||||
Validates all installed models.
|
||||
.SH "OPTIONS"
|
||||
.TP
|
||||
.I \-\-version
|
||||
Show program's version number and exit.
|
||||
.TP
|
||||
.I \-h, \-\-help
|
||||
Show this help message and exit.
|
||||
.TP
|
||||
.I \-\-settings=SETTINGS
|
||||
Python path to settings module, e.g. "myproject.settings.main". If
|
||||
this isn't provided, the DJANGO_SETTINGS_MODULE environment variable
|
||||
will be used.
|
||||
.TP
|
||||
.I \-\-pythonpath=PYTHONPATH
|
||||
Lets you manually add a directory the Python path,
|
||||
e.g. "/home/djangoprojects/myproject".
|
||||
.TP
|
||||
.I \-\-plain
|
||||
Use plain Python, not IPython, for the "shell" command.
|
||||
.TP
|
||||
.I \-\-noinput
|
||||
Do not prompt the user for input.
|
||||
.TP
|
||||
.I \-\-noreload
|
||||
Disable the development server's auto\-reloader.
|
||||
.TP
|
||||
.I \-\-verbosity=VERBOSITY
|
||||
Verbosity level: 0=minimal output, 1=normal output, 2=all output.
|
||||
.TP
|
||||
.I \-\-adminmedia=ADMIN_MEDIA_PATH
|
||||
Specifies the directory from which to serve admin media when using the development server.
|
||||
|
||||
.SH "ENVIRONMENT"
|
||||
.TP
|
||||
.I DJANGO_SETTINGS_MODULE
|
||||
In the absence of the
|
||||
.BI \-\-settings
|
||||
option, this environment variable defines the settings module to be read.
|
||||
It should be in Python-import form, e.g. "myproject.settings".
|
||||
|
||||
.SH "SEE ALSO"
|
||||
Full descriptions of all these options, with examples, as well as documentation
|
||||
for the rest of the Django framework, can be found on the Django site:
|
||||
.sp
|
||||
.I http://www.djangoproject.com/documentation/
|
||||
.sp
|
||||
or in the distributed documentation.
|
||||
.SH "AUTHORS/CREDITS"
|
||||
Originally developed at World Online in Lawrence, Kansas, USA. Refer to the
|
||||
AUTHORS file in the Django distribution for contributors.
|
||||
.sp
|
||||
.SH "LICENSE"
|
||||
New BSD license. For the full license text refer to the LICENSE file in the
|
||||
Django distribution.
|
||||
|
@ -447,6 +447,11 @@ and doesn't give a 404 response).
|
||||
|
||||
The admin represents this as an ``<input type="text">`` (a single-line input).
|
||||
|
||||
``URLField`` takes an optional argument, ``maxlength``, the maximum length (in
|
||||
characters) of the field. The maxlength is enforced at the database level and
|
||||
in Django's validation. If you don't specify ``maxlength``, a default of 200
|
||||
is used.
|
||||
|
||||
``USStateField``
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -303,6 +303,11 @@ is -- e.g., for ``DateField``, it's ``None`` instead of the empty string. For
|
||||
full details on each field's behavior in this case, see the "Empty value" note
|
||||
for each field in the "Built-in ``Field`` classes" section below.
|
||||
|
||||
You can write code to perform validation for particular form fields (based on
|
||||
their name) or for the form as a whole (considering combinations of various
|
||||
fields). More information about this is in the `Custom form and field
|
||||
validation`_ section, below.
|
||||
|
||||
Behavior of unbound forms
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -1212,6 +1217,84 @@ custom ``Field`` classes. To do this, just create a subclass of
|
||||
mentioned above (``required``, ``label``, ``initial``, ``widget``,
|
||||
``help_text``).
|
||||
|
||||
Custom form and field validation
|
||||
---------------------------------
|
||||
|
||||
Form validation happens when the data is cleaned. If you want to customise
|
||||
this process, there are various places you can change, each one serving a
|
||||
different purpose. Thee types of cleaning methods are run during form
|
||||
processing. These are normally executed when you call the ``is_valid()``
|
||||
method on a form. There are other things that can kick of cleaning and
|
||||
validation (accessing the ``errors`` attribute or calling ``full_clean()``
|
||||
directly), but normally they won't be needed.
|
||||
|
||||
In general, any cleaning method can raise ``ValidationError`` if there is a
|
||||
problem with the data it is processing, passing the relevant error message to
|
||||
the ``ValidationError`` constructor. If no ``ValidationError`` is raised, the
|
||||
method should return the cleaned (normalised) data as a Python object.
|
||||
|
||||
If you detect multiple errors during a cleaning method and wish to signal all
|
||||
of them to the form submittor, it is possible to pass a list of errors to the
|
||||
``ValidationError`` constructor.
|
||||
|
||||
The three types of cleaning methods are:
|
||||
|
||||
* The ``clean()`` method on a Field subclass. This is responsible
|
||||
for cleaning the data in a way that is generic for that type of field.
|
||||
For example, a FloatField will turn the data into a Python ``float`` or
|
||||
raise a ``ValidationError``.
|
||||
|
||||
* The ``clean_<fieldname>()`` method in a form subclass -- where
|
||||
``<fieldname>`` is replaced with the name of the form field attribute.
|
||||
This method does any cleaning that is specific to that particular
|
||||
attribute, unrelated to the type of field that it is. This method is not
|
||||
passed any parameters. You will need to look up the value of the field
|
||||
in ``self.cleaned_data`` and remember that it will be a Python object
|
||||
at this point, not the original string submitted in the form (it will be
|
||||
in ``cleaned_data`` because the general field ``clean()`` method, above,
|
||||
has already cleaned the data once).
|
||||
|
||||
For example, if you wanted to validate that the contents of a
|
||||
``CharField`` called ``serialnumber`` was unique,
|
||||
``clean_serialnumber()`` would be the right place to do this. You don't
|
||||
need a specific field (it's just a ``CharField``), but you want a
|
||||
formfield-specific piece of validation and, possibly,
|
||||
cleaning/normalizing the data.
|
||||
|
||||
* The Form subclass's ``clean()`` method. This method can perform
|
||||
any validation that requires access to multiple fields from the form at
|
||||
once. This is where you might put in things to check that if field ``A``
|
||||
is supplied, field ``B`` must contain a valid email address and the
|
||||
like. The data that this method returns is the final ``cleaned_data``
|
||||
attribute for the form, so don't forget to return the full list of
|
||||
cleaned data if you override this method (by default, ``Form.clean()``
|
||||
just returns ``self.cleaned_data``).
|
||||
|
||||
Note that any errors raised by your ``Form.clean()`` override will not
|
||||
be associated with any field in particular. They go into a special
|
||||
"field" (called ``__all__``, which you can access via the
|
||||
``non_field_errors()`` method if you need to.
|
||||
|
||||
These methods are run in the order given above, one field at a time. That is,
|
||||
for each field in the form (in the order they are declared in the form
|
||||
definition), the ``Field.clean()`` method (or it's override) is run, then
|
||||
``clean_<fieldname>()``. Finally, once those two methods are run for every
|
||||
field, the ``Form.clean()`` method, or it's override, is executed.
|
||||
|
||||
As mentioned above, any of these methods can raise a ``ValidationError``. For
|
||||
any field, if the ``Field.clean()`` method raises a ``ValidationError``, any
|
||||
field-specific cleaning method is not called. However, the cleaning methods
|
||||
for all remaining fields are still executed.
|
||||
|
||||
The ``clean()`` method for the ``Form`` class or subclass is always run. If
|
||||
that method raises a ``ValidationError``, ``cleaned_data`` will be an empty
|
||||
dictionary.
|
||||
|
||||
The previous paragraph means that if you are overriding ``Form.clean()``, you
|
||||
should iterate through ``self.cleaned_data.items()``, possibly considering the
|
||||
``_errors`` dictionary attribute on the form as well. In this way, you will
|
||||
already know which fields have passed thei individual validation requirements.
|
||||
|
||||
A simple example
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -21,3 +21,8 @@ done
|
||||
# Make sure we match foo.pyo and foo.pyc along with foo.py (but only once each)
|
||||
sed -e "/\.py[co]$/d" -e "s/\.py$/.py*/" DIRS FILES >INSTALLED_FILES
|
||||
|
||||
mkdir -p ${RPM_BUILD_ROOT}/%{_mandir}/man1/
|
||||
cp docs/man/* ${RPM_BUILD_ROOT}/%{_mandir}/man1/
|
||||
cat << EOF >> INSTALLED_FILES
|
||||
%doc %{_mandir}/man1/*"
|
||||
EOF
|
||||
|
@ -288,11 +288,11 @@ def fieldsTest(format, self):
|
||||
|
||||
obj = ComplexModel(field1='first',field2='second',field3='third')
|
||||
obj.save()
|
||||
|
||||
|
||||
# Serialize then deserialize the test database
|
||||
serialized_data = serializers.serialize(format, [obj], indent=2, fields=('field1','field3'))
|
||||
result = serializers.deserialize(format, serialized_data).next()
|
||||
|
||||
|
||||
# Check that the deserialized object contains data in only the serialized fields.
|
||||
self.assertEqual(result.object.field1, 'first')
|
||||
self.assertEqual(result.object.field2, '')
|
||||
@ -304,19 +304,20 @@ def streamTest(format, self):
|
||||
|
||||
obj = ComplexModel(field1='first',field2='second',field3='third')
|
||||
obj.save()
|
||||
|
||||
|
||||
# Serialize the test database to a stream
|
||||
stream = StringIO()
|
||||
stream = StringIO()
|
||||
serializers.serialize(format, [obj], indent=2, stream=stream)
|
||||
|
||||
|
||||
# Serialize normally for a comparison
|
||||
string_data = serializers.serialize(format, [obj], indent=2)
|
||||
|
||||
# Check that the two are the same
|
||||
self.assertEqual(string_data, stream.buffer())
|
||||
self.assertEqual(string_data, stream.getvalue())
|
||||
stream.close()
|
||||
|
||||
|
||||
for format in serializers.get_serializer_formats():
|
||||
setattr(SerializerTests, 'test_'+format+'_serializer', curry(serializerTest, format))
|
||||
setattr(SerializerTests, 'test_'+format+'_serializer_fields', curry(fieldsTest, format))
|
||||
setattr(SerializerTests, 'test_'+format+'_serializer_stream', curry(fieldsTest, format))
|
||||
if format != 'python':
|
||||
setattr(SerializerTests, 'test_'+format+'_serializer_stream', curry(streamTest, format))
|
||||
|
Loading…
x
Reference in New Issue
Block a user