# -*- coding: utf-8 -*- from __future__ import unicode_literals import copy import datetime import json import uuid from django.core.exceptions import NON_FIELD_ERRORS from django.core.files.uploadedfile import SimpleUploadedFile from django.core.validators import RegexValidator from django.forms import ( BooleanField, CharField, CheckboxSelectMultiple, ChoiceField, DateField, DateTimeField, EmailField, FileField, FloatField, Form, HiddenInput, ImageField, IntegerField, MultipleChoiceField, MultipleHiddenInput, MultiValueField, NullBooleanField, PasswordInput, RadioSelect, Select, SplitDateTimeField, SplitHiddenDateTimeWidget, Textarea, TextInput, TimeField, ValidationError, forms, ) from django.forms.utils import ErrorList from django.http import QueryDict from django.template import Context, Template from django.test import SimpleTestCase from django.test.utils import str_prefix from django.utils import six from django.utils.datastructures import MultiValueDict from django.utils.encoding import force_text, python_2_unicode_compatible from django.utils.html import format_html from django.utils.safestring import SafeData, mark_safe class Person(Form): first_name = CharField() last_name = CharField() birthday = DateField() class PersonNew(Form): first_name = CharField(widget=TextInput(attrs={'id': 'first_name_id'})) last_name = CharField() birthday = DateField() class FormsTestCase(SimpleTestCase): # A Form is a collection of Fields. It knows how to validate a set of data and it # knows how to render itself in a couple of default ways (e.g., an HTML table). # You can pass it data in __init__(), as a dictionary. def test_form(self): # Pass a dictionary to a Form's __init__(). p = Person({'first_name': 'John', 'last_name': 'Lennon', 'birthday': '1940-10-9'}) self.assertTrue(p.is_bound) self.assertEqual(p.errors, {}) self.assertTrue(p.is_valid()) self.assertHTMLEqual(p.errors.as_ul(), '') self.assertEqual(p.errors.as_text(), '') self.assertEqual(p.cleaned_data["first_name"], 'John') self.assertEqual(p.cleaned_data["last_name"], 'Lennon') self.assertEqual(p.cleaned_data["birthday"], datetime.date(1940, 10, 9)) self.assertHTMLEqual( str(p['first_name']), '' ) self.assertHTMLEqual( str(p['last_name']), '' ) self.assertHTMLEqual( str(p['birthday']), '' ) nonexistenterror = "Key u?'nonexistentfield' not found in 'Person'" with six.assertRaisesRegex(self, KeyError, nonexistenterror): p['nonexistentfield'] self.fail('Attempts to access non-existent fields should fail.') form_output = [] for boundfield in p: form_output.append(str(boundfield)) self.assertHTMLEqual( '\n'.join(form_output), """ """ ) form_output = [] for boundfield in p: form_output.append([boundfield.label, boundfield.data]) self.assertEqual(form_output, [ ['First name', 'John'], ['Last name', 'Lennon'], ['Birthday', '1940-10-9'] ]) self.assertHTMLEqual( str(p), """ """ ) def test_empty_dict(self): # Empty dictionaries are valid, too. p = Person({}) self.assertTrue(p.is_bound) self.assertEqual(p.errors['first_name'], ['This field is required.']) self.assertEqual(p.errors['last_name'], ['This field is required.']) self.assertEqual(p.errors['birthday'], ['This field is required.']) self.assertFalse(p.is_valid()) self.assertEqual(p.cleaned_data, {}) self.assertHTMLEqual( str(p), """ """ ) self.assertHTMLEqual( p.as_table(), """ """ ) self.assertHTMLEqual( p.as_ul(), """
  • """ ) self.assertHTMLEqual( p.as_p(), """

    """ ) def test_unbound_form(self): # If you don't pass any values to the Form's __init__(), or if you pass None, # the Form will be considered unbound and won't do any validation. Form.errors # will be an empty dictionary *but* Form.is_valid() will return False. p = Person() self.assertFalse(p.is_bound) self.assertEqual(p.errors, {}) self.assertFalse(p.is_valid()) try: p.cleaned_data self.fail('Attempts to access cleaned_data when validation fails should fail.') except AttributeError: pass self.assertHTMLEqual( str(p), """ """ ) self.assertHTMLEqual( p.as_table(), """ """ ) self.assertHTMLEqual( p.as_ul(), """
  • """ ) self.assertHTMLEqual( p.as_p(), """

    """ ) def test_unicode_values(self): # Unicode values are handled properly. p = Person({ 'first_name': 'John', 'last_name': '\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111', 'birthday': '1940-10-9' }) self.assertHTMLEqual( p.as_table(), '' '\n' '' '\n' '' '' ) self.assertHTMLEqual( p.as_ul(), '
  • ' '
  • \n' '
  • ' '
  • \n' '
  • ' '
  • ' ) self.assertHTMLEqual( p.as_p(), '

    ' '

    \n' '

    ' '

    \n' '

    ' '

    ' ) p = Person({'last_name': 'Lennon'}) self.assertEqual(p.errors['first_name'], ['This field is required.']) self.assertEqual(p.errors['birthday'], ['This field is required.']) self.assertFalse(p.is_valid()) self.assertDictEqual( p.errors, {'birthday': ['This field is required.'], 'first_name': ['This field is required.']} ) self.assertEqual(p.cleaned_data, {'last_name': 'Lennon'}) self.assertEqual(p['first_name'].errors, ['This field is required.']) self.assertHTMLEqual( p['first_name'].errors.as_ul(), '' ) self.assertEqual(p['first_name'].errors.as_text(), '* This field is required.') p = Person() self.assertHTMLEqual(str(p['first_name']), '') self.assertHTMLEqual(str(p['last_name']), '') self.assertHTMLEqual(str(p['birthday']), '') def test_cleaned_data_only_fields(self): # 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 cleaned_data contains only the form's fields. data = { 'first_name': 'John', 'last_name': 'Lennon', 'birthday': '1940-10-9', 'extra1': 'hello', 'extra2': 'hello', } p = Person(data) self.assertTrue(p.is_valid()) self.assertEqual(p.cleaned_data['first_name'], 'John') self.assertEqual(p.cleaned_data['last_name'], 'Lennon') self.assertEqual(p.cleaned_data['birthday'], datetime.date(1940, 10, 9)) def test_optional_data(self): # 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 cleaned_data includes it. For CharFields, it's set to the # empty string. class OptionalPersonForm(Form): first_name = CharField() last_name = CharField() nick_name = CharField(required=False) data = {'first_name': 'John', 'last_name': 'Lennon'} f = OptionalPersonForm(data) self.assertTrue(f.is_valid()) self.assertEqual(f.cleaned_data['nick_name'], '') self.assertEqual(f.cleaned_data['first_name'], 'John') self.assertEqual(f.cleaned_data['last_name'], 'Lennon') # For DateFields, it's set to None. class OptionalPersonForm(Form): first_name = CharField() last_name = CharField() birth_date = DateField(required=False) data = {'first_name': 'John', 'last_name': 'Lennon'} f = OptionalPersonForm(data) self.assertTrue(f.is_valid()) self.assertEqual(f.cleaned_data['birth_date'], None) self.assertEqual(f.cleaned_data['first_name'], 'John') self.assertEqual(f.cleaned_data['last_name'], 'Lennon') def test_auto_id(self): # "auto_id" tells the Form to add an "id" attribute to each form element. # If it's a string that contains '%s', Django will use that as a format string # into which the field's name will be inserted. It will also put a