1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

unicode: Merged from trunk to [5237].

git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5241 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-05-14 19:42:13 +00:00
parent 36c508d1ed
commit 57ced25606
20 changed files with 2931 additions and 85 deletions

View File

@ -86,6 +86,7 @@ answer newbie questions, and generally made Django that much better:
Alex Dedul
deric@monowerks.com
Max Derkachev <mderk@yandex.ru>
Jordan Dimov <s3x3y1@gmail.com>
dne@mayonnaise.net
Maximillian Dornseif <md@hudora.de>
Jeremy Dunck <http://dunck.us/>

View File

@ -38,6 +38,7 @@ LANGUAGE_CODE = 'en-us'
LANGUAGES = (
('ar', gettext_noop('Arabic')),
('bn', gettext_noop('Bengali')),
('bg', gettext_noop('Bulgarian')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,106 @@
# translation of djangojs.po to Bulgarian
#
msgid ""
msgstr ""
"Project-Id-Version: djangojs\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2007-05-12 17:51+0300\n"
"Last-Translator: Jordan Dimov <s3x3y1@gmail.com>\n"
"Language-Team: Bulgarian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Налични %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Избери всички"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Добави"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Премахни"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Избрахме %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Направете своя избор и щракнете "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Изчисти всички"
#: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr "Януари Февруари Март Април Май Юни Юли Август Септември Октомври Ноември Декември"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Неделя Понеделник Вторник Сряда Четвъртък Петък Събота"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "Н П В С Ч П С"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now"
msgstr "Сега"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
msgid "Clock"
msgstr "Часовник"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
msgid "Choose a time"
msgstr "Избери време"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Midnight"
msgstr "Полунощ"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m."
msgstr "6 a.m."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon"
msgstr "По обяд"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
msgid "Cancel"
msgstr "Отказ"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
msgid "Today"
msgstr "Днес"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
msgid "Calendar"
msgstr "Календар"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
msgid "Yesterday"
msgstr "Вчера"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "Утре"

View File

@ -24,7 +24,7 @@ Usage
Subclass FormPreview and define a done() method:
def done(self, request, clean_data):
def done(self, request, cleaned_data):
# ...
This method takes an HttpRequest object and a dictionary of the form data after
@ -113,7 +113,7 @@ class FormPreview(object):
if f.is_valid():
if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
return self.failed_hash(request) # Security hash failed.
return self.done(request, f.clean_data)
return self.done(request, f.cleaned_data)
else:
return render_to_response(self.form_template,
{'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
@ -160,6 +160,9 @@ class FormPreview(object):
# METHODS SUBCLASSES MUST OVERRIDE ########################################
def done(self, request, clean_data):
"Does something with the clean_data and returns an HttpResponseRedirect."
def done(self, request, cleaned_data):
"""
Does something with the cleaned_data and returns an
HttpResponseRedirect.
"""
raise NotImplementedError('You must define a done() method on your %s subclass.' % self.__class__.__name__)

View File

@ -1404,21 +1404,25 @@ def load_data(fixture_labels, verbosity=1):
if verbosity > 1:
print "No %s fixture '%s' in %s." % \
(format, fixture_name, humanize(fixture_dir))
if count[0] == 0:
if verbosity > 0:
print "No fixtures found."
else:
if verbosity > 0:
print "Installed %d object(s) from %d fixture(s)" % tuple(count)
if count[0] > 0:
sequence_sql = backend.get_sql_sequence_reset(style, models)
if sequence_sql:
if verbosity > 1:
print "Resetting sequences"
for line in sequence_sql:
cursor.execute(line)
transaction.commit()
transaction.leave_transaction_management()
if count[0] == 0:
if verbosity > 0:
print "No fixtures found."
else:
if verbosity > 0:
print "Installed %d object(s) from %d fixture(s)" % tuple(count)
load_data.help_doc = 'Installs the named fixture(s) in the database'
load_data.args = "[--verbosity] fixture, fixture, ..."

View File

@ -37,7 +37,7 @@ class Serializer(base.Serializer):
def handle_fk_field(self, obj, field):
related = getattr(obj, field.name)
if related is not None:
related = related._get_pk_val()
related = getattr(related, field.rel.field_name)
self._current[field.name] = related
def handle_m2m_field(self, obj, field):
@ -80,7 +80,10 @@ def Deserializer(object_list, **options):
# Handle FK fields
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
data[field.attname] = field.rel.to._meta.pk.to_python(field_value)
if field_value:
data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
else:
data[field.attname] = None
# Handle all other fields
else:

View File

@ -82,7 +82,7 @@ class Serializer(base.Serializer):
self._start_relational_field(field)
related = getattr(obj, field.name)
if related is not None:
self.xml.characters(str(related._get_pk_val()))
self.xml.characters(str(getattr(related, field.rel.field_name)))
else:
self.xml.addQuickElement("None")
self.xml.endElement("field")
@ -181,7 +181,7 @@ class Deserializer(base.Deserializer):
if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None':
return None
else:
return field.rel.to._meta.pk.to_python(
return field.rel.to._meta.get_field(field.rel.field_name).to_python(
getInnerText(node).strip().encode(self.encoding))
def _handle_m2m_field_node(self, node, field):

View File

@ -169,13 +169,13 @@ class BaseForm(StrAndUnicode):
def full_clean(self):
"""
Cleans all of self.data and populates self.__errors and self.clean_data.
Cleans all of self.data and populates self.__errors and self.cleaned_data.
"""
errors = ErrorDict()
if not self.is_bound: # Stop further processing.
self.__errors = errors
return
self.clean_data = {}
self.cleaned_data = {}
for name, field in self.fields.items():
# value_from_datadict() gets the data from the dictionary.
# Each widget type knows how to retrieve its own data, because some
@ -183,18 +183,18 @@ class BaseForm(StrAndUnicode):
value = field.widget.value_from_datadict(self.data, self.add_prefix(name))
try:
value = field.clean(value)
self.clean_data[name] = value
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.clean_data[name] = value
self.cleaned_data[name] = value
except ValidationError, e:
errors[name] = e.messages
try:
self.clean_data = self.clean()
self.cleaned_data = self.clean()
except ValidationError, e:
errors[NON_FIELD_ERRORS] = e.messages
if errors:
delattr(self, 'clean_data')
delattr(self, 'cleaned_data')
self.__errors = errors
def clean(self):
@ -204,7 +204,7 @@ class BaseForm(StrAndUnicode):
not be associated with a particular field; it will have a special-case
association with the field named '__all__'.
"""
return self.clean_data
return self.cleaned_data
class Form(BaseForm):
"A collection of Fields, plus their associated data."

View File

@ -15,7 +15,7 @@ __all__ = ('save_instance', 'form_for_model', 'form_for_instance', 'form_for_fie
def save_instance(form, instance, fields=None, fail_message='saved', commit=True):
"""
Saves bound Form ``form``'s clean_data into model instance ``instance``.
Saves bound Form ``form``'s cleaned_data into model instance ``instance``.
Assumes ``form`` has a field for every non-AutoField database field in
``instance``. If commit=True, then the changes to ``instance`` will be
@ -25,20 +25,20 @@ def save_instance(form, instance, fields=None, fail_message='saved', commit=True
opts = instance.__class__._meta
if form.errors:
raise ValueError("The %s could not be %s because the data didn't validate." % (opts.object_name, fail_message))
clean_data = form.clean_data
cleaned_data = form.cleaned_data
for f in opts.fields:
if not f.editable or isinstance(f, models.AutoField) or not f.name in clean_data:
if not f.editable or isinstance(f, models.AutoField) or not f.name in cleaned_data:
continue
if fields and f.name not in fields:
continue
setattr(instance, f.name, clean_data[f.name])
setattr(instance, f.name, cleaned_data[f.name])
if commit:
instance.save()
for f in opts.many_to_many:
if fields and f.name not in fields:
continue
if f.name in clean_data:
setattr(instance, f.attname, clean_data[f.name])
if f.name in cleaned_data:
setattr(instance, f.attname, cleaned_data[f.name])
# GOTCHA: If many-to-many data is given and commit=False, the many-to-many
# data will be lost. This happens because a many-to-many options cannot be
# set on an object until after it's saved. Maybe we should raise an

View File

@ -62,7 +62,7 @@ class TestCase(unittest.TestCase):
"""
self.assertEqual(response.status_code, status_code,
"Response didn't redirect: Reponse code was %d (expected %d)" %
"Response didn't redirect as expected: Reponse code was %d (expected %d)" %
(response.status_code, status_code))
scheme, netloc, path, params, query, fragment = urlparse(response['Location'])
self.assertEqual(path, expected_path,
@ -70,7 +70,7 @@ class TestCase(unittest.TestCase):
redirect_response = self.client.get(path)
self.assertEqual(redirect_response.status_code, target_status_code,
"Couldn't retrieve redirection page '%s': response code was %d (expected %d)" %
(path, response.status_code, status_code))
(path, redirect_response.status_code, target_status_code))
def assertContains(self, response, text, count=1, status_code=200):
"""Assert that a response indicates that a page was retreived successfully,

View File

@ -230,7 +230,7 @@ object. Regardless of whether you pass it a string in the format
it's valid.
Once you've created a ``Form`` instance with a set of data and validated it,
you can access the clean data via the ``clean_data`` attribute of the ``Form``
you can access the clean data via the ``cleaned_data`` attribute of the ``Form``
object::
>>> data = {'subject': 'hello',
@ -240,7 +240,7 @@ object::
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.clean_data
>>> f.cleaned_data
{'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
Note that any text-based field -- such as ``CharField`` or ``EmailField`` --
@ -248,7 +248,7 @@ always cleans the input into a Unicode string. We'll cover the encoding
implications later in this document.
If your data does *not* validate, your ``Form`` instance will not have a
``clean_data`` attribute::
``cleaned_data`` attribute::
>>> data = {'subject': '',
... 'message': 'Hi there',
@ -257,15 +257,15 @@ If your data does *not* validate, your ``Form`` instance will not have a
>>> f = ContactForm(data)
>>> f.is_valid()
False
>>> f.clean_data
>>> f.cleaned_data
Traceback (most recent call last):
...
AttributeError: 'ContactForm' object has no attribute 'clean_data'
AttributeError: 'ContactForm' object has no attribute 'cleaned_data'
``clean_data`` will always *only* contain a key for fields defined in the
``cleaned_data`` will always *only* contain a key for fields defined in the
``Form``, even if you pass extra data when you define the ``Form``. In this
example, we pass a bunch of extra fields to the ``ContactForm`` constructor,
but ``clean_data`` contains only the form's fields::
but ``cleaned_data`` contains only the form's fields::
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
@ -277,13 +277,13 @@ but ``clean_data`` contains only the form's fields::
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.clean_data # Doesn't contain extra_field_1, etc.
>>> f.cleaned_data # Doesn't contain extra_field_1, etc.
{'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
``clean_data`` will include a key and value for *all* fields defined in the
``cleaned_data`` will include a key and value for *all* fields defined in the
``Form``, even if the data didn't include a value for fields that are not
required. In this example, the data dictionary doesn't include a value for the
``nick_name`` field, but ``clean_data`` includes it, with an empty value::
``nick_name`` field, but ``cleaned_data`` includes it, with an empty value::
>>> class OptionalPersonForm(Form):
... first_name = CharField()
@ -293,10 +293,10 @@ required. In this example, the data dictionary doesn't include a value for the
>>> f = OptionalPersonForm(data)
>>> f.is_valid()
True
>>> f.clean_data
>>> f.cleaned_data
{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
In this above example, the ``clean_data`` value for ``nick_name`` is set to an
In this above example, the ``cleaned_data`` value for ``nick_name`` is set to an
empty string, because ``nick_name`` is ``CharField``, and ``CharField``\s treat
empty values as an empty string. Each field type knows what its "blank" value
is -- e.g., for ``DateField``, it's ``None`` instead of the empty string.
@ -308,10 +308,10 @@ It's meaningless to request "clean" data in a form with no data, but, for the
record, here's what happens with unbound forms::
>>> f = ContactForm()
>>> f.clean_data
>>> f.cleaned_data
Traceback (most recent call last):
...
AttributeError: 'ContactForm' object has no attribute 'clean_data'
AttributeError: 'ContactForm' object has no attribute 'cleaned_data'
Outputting forms as HTML
------------------------

View File

@ -18,7 +18,7 @@ other Form, with one additional method: save(). The save()
method updates the model instance. It also takes a commit=True parameter.
The function django.newforms.save_instance() takes a bound form instance and a
model instance and saves the form's clean_data into the instance. It also takes
model instance and saves the form's cleaned_data into the instance. It also takes
a commit=True parameter.
"""
@ -94,7 +94,7 @@ __test__ = {'API_TESTS': """
>>> f = CategoryForm({'name': 'Entertainment', 'url': 'entertainment'})
>>> f.is_valid()
True
>>> f.clean_data
>>> f.cleaned_data
{'url': u'entertainment', 'name': u'Entertainment'}
>>> obj = f.save()
>>> obj
@ -105,7 +105,7 @@ True
>>> f = CategoryForm({'name': "It's a test", 'url': 'test'})
>>> f.is_valid()
True
>>> f.clean_data
>>> f.cleaned_data
{'url': u'test', 'name': u"It's a test"}
>>> obj = f.save()
>>> obj
@ -119,7 +119,7 @@ save() on the resulting model instance.
>>> f = CategoryForm({'name': 'Third test', 'url': 'third'})
>>> f.is_valid()
True
>>> f.clean_data
>>> f.cleaned_data
{'url': u'third', 'name': u'Third test'}
>>> obj = f.save(commit=False)
>>> obj
@ -134,10 +134,10 @@ If you call save() with invalid data, you'll get a ValueError.
>>> f = CategoryForm({'name': '', 'url': 'foo'})
>>> f.errors
{'name': [u'This field is required.']}
>>> f.clean_data
>>> f.cleaned_data
Traceback (most recent call last):
...
AttributeError: 'CategoryForm' object has no attribute 'clean_data'
AttributeError: 'CategoryForm' object has no attribute 'cleaned_data'
>>> f.save()
Traceback (most recent call last):
...
@ -524,6 +524,6 @@ ValidationError: [u'Select a valid choice. 10 is not one of the available choice
>>> f = PhoneNumberForm({'phone': '(312) 555-1212', 'description': 'Assistance'})
>>> f.is_valid()
True
>>> f.clean_data
>>> f.cleaned_data
{'phone': u'312-555-1212', 'description': u'Assistance'}
"""}

View File

@ -52,4 +52,18 @@ Russian abbreviations "мес." and "шт.".
u'\u0448\u0442.'
>>> f.clean('\xd1\x88\xd1\x82.')
u'\u0448\u0442.'
#######################
# Miscellaneous Tests #
#######################
There once was a problem with Form fields called "data". Let's make sure that
doesn't come back.
>>> class DataForm(Form):
... data = CharField(max_length=10)
>>> f = DataForm({'data': 'xyzzy'})
>>> f.is_valid()
True
>>> f.cleaned_data
{'data': u'xyzzy'}
"""

View File

@ -1774,7 +1774,7 @@ True
u''
>>> p.errors.as_text()
u''
>>> p.clean_data
>>> p.cleaned_data
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
>>> print p['first_name']
<input type="text" name="first_name" value="John" id="id_first_name" />
@ -1810,10 +1810,10 @@ True
{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']}
>>> p.is_valid()
False
>>> p.clean_data
>>> p.cleaned_data
Traceback (most recent call last):
...
AttributeError: 'Person' object has no attribute 'clean_data'
AttributeError: 'Person' object has no attribute 'cleaned_data'
>>> print p
<tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr>
<tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr>
@ -1844,10 +1844,10 @@ False
{}
>>> p.is_valid()
False
>>> p.clean_data
>>> p.cleaned_data
Traceback (most recent call last):
...
AttributeError: 'Person' object has no attribute 'clean_data'
AttributeError: 'Person' object has no attribute 'cleaned_data'
>>> print p
<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr>
<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
@ -1886,10 +1886,10 @@ u'<ul class="errorlist"><li>first_name<ul class="errorlist"><li>This field is re
* This field is required.
* birthday
* This field is required.
>>> p.clean_data
>>> p.cleaned_data
Traceback (most recent call last):
...
AttributeError: 'Person' object has no attribute 'clean_data'
AttributeError: 'Person' object has no attribute 'cleaned_data'
>>> p['first_name'].errors
[u'This field is required.']
>>> p['first_name'].errors.as_ul()
@ -1905,21 +1905,21 @@ u'* This field is required.'
>>> print p['birthday']
<input type="text" name="birthday" id="id_birthday" />
clean_data will always *only* contain a key for fields defined in the
cleaned_data will always *only* contain a key for fields defined in the
Form, even if you pass extra data when you define the Form. In this
example, we pass a bunch of extra fields to the form constructor,
but clean_data contains only the form's fields.
but cleaned_data contains only the form's fields.
>>> data = {'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9', 'extra1': 'hello', 'extra2': 'hello'}
>>> p = Person(data)
>>> p.is_valid()
True
>>> p.clean_data
>>> p.cleaned_data
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
clean_data will include a key and value for *all* fields defined in the Form,
cleaned_data will include a key and value for *all* fields defined in the Form,
even if the Form's data didn't include a value for fields that are not
required. In this example, the data dictionary doesn't include a value for the
"nick_name" field, but clean_data includes it. For CharFields, it's set to the
"nick_name" field, but cleaned_data includes it. For CharFields, it's set to the
empty string.
>>> class OptionalPersonForm(Form):
... first_name = CharField()
@ -1929,7 +1929,7 @@ empty string.
>>> f = OptionalPersonForm(data)
>>> f.is_valid()
True
>>> f.clean_data
>>> f.cleaned_data
{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
For DateFields, it's set to None.
@ -1941,7 +1941,7 @@ For DateFields, it's set to None.
>>> f = OptionalPersonForm(data)
>>> f.is_valid()
True
>>> f.clean_data
>>> f.cleaned_data
{'birth_date': None, 'first_name': u'John', 'last_name': u'Lennon'}
"auto_id" tells the Form to add an "id" attribute to each form element.
@ -2292,19 +2292,19 @@ returns a list of input.
>>> f = SongForm({'name': 'Yesterday', 'composers': ['J']}, auto_id=False)
>>> f.errors
{}
>>> f.clean_data
>>> f.cleaned_data
{'composers': [u'J'], 'name': u'Yesterday'}
>>> f = SongForm({'name': 'Yesterday', 'composers': ['J', 'P']}, auto_id=False)
>>> f.errors
{}
>>> f.clean_data
>>> f.cleaned_data
{'composers': [u'J', u'P'], 'name': u'Yesterday'}
Validation errors are HTML-escaped when output as HTML.
>>> class EscapingForm(Form):
... special_name = CharField()
... def clean_special_name(self):
... raise ValidationError("Something's wrong with '%s'" % self.clean_data['special_name'])
... raise ValidationError("Something's wrong with '%s'" % self.cleaned_data['special_name'])
>>> f = EscapingForm({'special_name': "Nothing to escape"}, auto_id=False)
>>> print f
@ -2319,7 +2319,7 @@ There are a couple of ways to do multiple-field validation. If you want the
validation message to be associated with a particular field, implement the
clean_XXX() method on the Form, where XXX is the field name. As in
Field.clean(), the clean_XXX() method should return the cleaned value. In the
clean_XXX() method, you have access to self.clean_data, which is a dictionary
clean_XXX() method, you have access to self.cleaned_data, which is a dictionary
of all the data that has been cleaned *so far*, in order by the fields,
including the current field (e.g., the field XXX if you're in clean_XXX()).
>>> class UserRegistration(Form):
@ -2327,9 +2327,9 @@ including the current field (e.g., the field XXX if you're in clean_XXX()).
... password1 = CharField(widget=PasswordInput)
... password2 = CharField(widget=PasswordInput)
... def clean_password2(self):
... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']:
... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']:
... raise ValidationError(u'Please make sure your passwords match.')
... return self.clean_data['password2']
... return self.cleaned_data['password2']
>>> f = UserRegistration(auto_id=False)
>>> f.errors
{}
@ -2342,14 +2342,14 @@ including the current field (e.g., the field XXX if you're in clean_XXX()).
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False)
>>> f.errors
{}
>>> f.clean_data
>>> f.cleaned_data
{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'}
Another way of doing multiple-field validation is by implementing the
Form's clean() method. If you do this, any ValidationError raised by that
method will not be associated with a particular field; it will have a
special-case association with the field named '__all__'.
Note that in Form.clean(), you have access to self.clean_data, a dictionary of
Note that in Form.clean(), you have access to self.cleaned_data, a dictionary of
all the fields/values that have *not* raised a ValidationError. Also note
Form.clean() is required to return a dictionary of all clean data.
>>> class UserRegistration(Form):
@ -2357,9 +2357,9 @@ Form.clean() is required to return a dictionary of all clean data.
... password1 = CharField(widget=PasswordInput)
... password2 = CharField(widget=PasswordInput)
... def clean(self):
... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']:
... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']:
... raise ValidationError(u'Please make sure your passwords match.')
... return self.clean_data
... return self.cleaned_data
>>> f = UserRegistration(auto_id=False)
>>> f.errors
{}
@ -2386,7 +2386,7 @@ Form.clean() is required to return a dictionary of all clean data.
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False)
>>> f.errors
{}
>>> f.clean_data
>>> f.cleaned_data
{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'}
# Dynamic construction ########################################################
@ -2954,7 +2954,7 @@ actual field name.
{}
>>> p.is_valid()
True
>>> p.clean_data
>>> p.cleaned_data
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
Let's try submitting some bad data to make sure form.errors and field.errors
@ -2998,12 +2998,12 @@ of the same form.
>>> p1 = Person(data, prefix='person1')
>>> p1.is_valid()
True
>>> p1.clean_data
>>> p1.cleaned_data
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
>>> p2 = Person(data, prefix='person2')
>>> p2.is_valid()
True
>>> p2.clean_data
>>> p2.cleaned_data
{'first_name': u'Jim', 'last_name': u'Morrison', 'birthday': datetime.date(1943, 12, 8)}
By default, forms append a hyphen between the prefix and the field name, but a
@ -3029,7 +3029,7 @@ self.prefix.
>>> p = Person(data, prefix='foo')
>>> p.is_valid()
True
>>> p.clean_data
>>> p.cleaned_data
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
# Forms with NullBooleanFields ################################################
@ -3091,16 +3091,16 @@ is different than its data. This is handled transparently, though.
... password1 = CharField(widget=PasswordInput)
... password2 = CharField(widget=PasswordInput)
... def clean(self):
... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']:
... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']:
... raise ValidationError(u'Please make sure your passwords match.')
... return self.clean_data
... return self.cleaned_data
>>> def my_function(method, post_data):
... if method == 'POST':
... form = UserRegistration(post_data, auto_id=False)
... else:
... form = UserRegistration(auto_id=False)
... if form.is_valid():
... return 'VALID: %r' % form.clean_data
... return 'VALID: %r' % form.cleaned_data
... t = Template('<form action="" method="post">\n<table>\n{{ form }}\n</table>\n<input type="submit" />\n</form>')
... return t.render(Context({'form': form}))
@ -3138,9 +3138,9 @@ VALID: {'username': u'adrian', 'password1': u'secret', 'password2': u'secret'}
... password1 = CharField(widget=PasswordInput)
... password2 = CharField(widget=PasswordInput)
... def clean(self):
... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']:
... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']:
... raise ValidationError(u'Please make sure your passwords match.')
... return self.clean_data
... return self.cleaned_data
You have full flexibility in displaying form fields in a template. Just pass a
Form instance to the template, and use "dot" access to refer to individual
@ -3490,7 +3490,7 @@ ValidationError: [u'This field is required.']
</select>
<input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" /><input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" /></td></tr>
>>> f.clean_data
>>> f.cleaned_data
{'field1': u'some text,JP,2007-04-25 06:24:00'}
#################################

View File

@ -101,6 +101,12 @@ class Anchor(models.Model):
data = models.CharField(maxlength=30)
class UniqueAnchor(models.Model):
"""This is a model that can be used as
something for other models to point at"""
data = models.CharField(unique=True, maxlength=30)
class FKData(models.Model):
data = models.ForeignKey(Anchor, null=True)
@ -116,6 +122,10 @@ class FKSelfData(models.Model):
class M2MSelfData(models.Model):
data = models.ManyToManyField('self', null=True, symmetrical=False)
class FKDataToField(models.Model):
data = models.ForeignKey(UniqueAnchor, null=True, to_field='data')
# The following test classes are for validating the
# deserialization of objects that use a user-defined
# field as the primary key.

View File

@ -159,6 +159,7 @@ The end."""),
(data_obj, 300, Anchor, "Anchor 1"),
(data_obj, 301, Anchor, "Anchor 2"),
(data_obj, 302, UniqueAnchor, "UAnchor 1"),
(fk_obj, 400, FKData, 300), # Post reference
(fk_obj, 401, FKData, 500), # Pre reference
@ -184,8 +185,13 @@ The end."""),
(m2m_obj, 445, M2MSelfData, []),
(m2m_obj, 446, M2MSelfData, []),
(fk_obj, 450, FKDataToField, "UAnchor 1"),
(fk_obj, 451, FKDataToField, "UAnchor 2"),
(fk_obj, 452, FKDataToField, None),
(data_obj, 500, Anchor, "Anchor 3"),
(data_obj, 501, Anchor, "Anchor 4"),
(data_obj, 502, UniqueAnchor, "UAnchor 2"),
(pk_obj, 601, BooleanPKData, True),
(pk_obj, 602, BooleanPKData, False),

View File

@ -61,6 +61,34 @@ class AssertTemplateUsedTests(TestCase):
except AssertionError, e:
self.assertEquals(str(e), "Template 'Valid POST Template' was not one of the templates used to render the response. Templates used: form_view.html, base.html")
class AssertRedirectsTests(TestCase):
def test_redirect_page(self):
"An assertion is raised if the original page couldn't be retrieved as expected"
# This page will redirect with code 301, not 302
response = self.client.get('/test_client/permanent_redirect_view/')
try:
self.assertRedirects(response, '/test_client/get_view/')
except AssertionError, e:
self.assertEquals(str(e), "Response didn't redirect as expected: Reponse code was 301 (expected 302)")
def test_incorrect_target(self):
"An assertion is raised if the response redirects to another target"
response = self.client.get('/test_client/permanent_redirect_view/')
try:
# Should redirect to get_view
self.assertRedirects(response, '/test_client/some_view/')
except AssertionError, e:
self.assertEquals(str(e), "Response didn't redirect as expected: Reponse code was 301 (expected 302)")
def test_target_page(self):
"An assertion is raised if the reponse redirect target cannot be retrieved as expected"
response = self.client.get('/test_client/double_redirect_view/')
try:
# The redirect target responds with a 301 code, not 200
self.assertRedirects(response, '/test_client/permanent_redirect_view/')
except AssertionError, e:
self.assertEquals(str(e), "Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)")
class AssertFormErrorTests(TestCase):
def test_unknown_form(self):
"An assertion is raised if the form name is unknown"