Django

Code

Changeset 4159

Show
Ignore:
Timestamp:
12/04/06 15:12:29 (3 years ago)
Author:
jpellerin
Message:

[multi-db] Merged trunk to [4158]. Some tests still failing.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/multiple-db-support/AUTHORS

    r4158 r4159  
    152152    sopel 
    153153    Thomas Steinacher <tom@eggdrop.ch> 
     154    nowell strite 
    154155    Radek Švarz <http://www.svarz.cz/translate/> 
    155156    Swaroop C H <http://www.swaroopch.info> 
  • django/branches/multiple-db-support/django/conf/project_template/urls.py

    r2809 r4159  
    33urlpatterns = patterns('', 
    44    # Example: 
    5     # (r'^{{ project_name }}/', include('{{ project_name }}.apps.foo.urls.foo')), 
     5    # (r'^{{ project_name }}/', include('{{ project_name }}.foo.urls')), 
    66 
    77    # Uncomment this for admin: 
  • django/branches/multiple-db-support/django/contrib/sitemaps/templates/sitemap_index.xml

    r4158 r4159  
    11<?xml version="1.0" encoding="UTF-8"?> 
    2 <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemapindex/0.9"> 
     2<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
    33{% for location in sitemaps %}<sitemap><loc>{{ location|escape }}</loc></sitemap>{% endfor %} 
    44</sitemapindex> 
  • django/branches/multiple-db-support/django/core/handlers/base.py

    r4156 r4159  
    8585            # Complain if the view returned None (a common error). 
    8686            if response is None: 
    87                 raise ValueError, "The view %s.%s didn't return an HttpResponse object." % (callback.__module__, callback.func_name) 
     87                try: 
     88                    view_name = callback.func_name # If it's a function 
     89                except AttributeError: 
     90                    view_name = callback.__class__.__name__ + '.__call__' # If it's a class 
     91                raise ValueError, "The view %s.%s didn't return an HttpResponse object." % (callback.__module__, view_name) 
    8892 
    8993            return response 
  • django/branches/multiple-db-support/django/core/handlers/wsgi.py

    r4158 r4159  
    6363    """ 
    6464    if not size: 
    65         return copyfileobj(fsrc, fdst, length) 
     65        return 
    6666    while size > 0: 
    6767        buf = fsrc.read(min(length, size)) 
     
    158158        except AttributeError: 
    159159            buf = StringIO() 
    160             # CONTENT_LENGTH might be absent if POST doesn't have content at all (lighttpd) 
    161             content_length = int(self.environ.get('CONTENT_LENGTH', 0)) 
     160            try: 
     161                # CONTENT_LENGTH might be absent if POST doesn't have content at all (lighttpd) 
     162                content_length = int(self.environ.get('CONTENT_LENGTH', 0)) 
     163            except ValueError: # if CONTENT_LENGTH was empty string or not an integer 
     164                content_length = 0 
    162165            safe_copyfileobj(self.environ['wsgi.input'], buf, size=content_length) 
    163166            self._raw_post_data = buf.getvalue() 
  • django/branches/multiple-db-support/django/db/models/fields/__init__.py

    r4157 r4159  
    458458    def get_db_prep_save(self, value): 
    459459        # Casts dates into string format for entry into database. 
    460         if isinstance(value, datetime.datetime): 
    461             value = value.date().strftime('%Y-%m-%d') 
    462         elif isinstance(value, datetime.date): 
     460        if value is not None: 
    463461            value = value.strftime('%Y-%m-%d') 
    464462        return Field.get_db_prep_save(self, value) 
     
    490488    def pre_save(self, model_instance, add): 
    491489        value = super(DateField, self).pre_save(model_instance, add) 
    492         if isinstance(value, datetime.datetime)
     490        if value is not None
    493491            # MySQL will throw a warning if microseconds are given, because it 
    494492            # doesn't support microseconds. 
     
    502500        if value is not None: 
    503501            value = str(value) 
    504         elif isinstance(value, datetime.date): 
    505             # MySQL will throw a warning if microseconds are given, because it 
    506             # doesn't support microseconds. 
    507             if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): 
    508                 value = datetime.datetime(value.year, value.month, value.day, microsecond=0) 
    509             value = str(value) 
    510              
    511502        return Field.get_db_prep_save(self, value) 
    512503 
  • django/branches/multiple-db-support/django/http/__init__.py

    r4139 r4159  
    209209            self.cookies[key]['path'] = path 
    210210        if domain is not None: 
    211             self.cookies[key]['domain'] = path 
     211            self.cookies[key]['domain'] = domain 
    212212        self.cookies[key]['expires'] = 0 
    213213        self.cookies[key]['max-age'] = 0 
  • django/branches/multiple-db-support/django/newforms/fields.py

    r4158 r4159  
    7777        """ 
    7878        super(IntegerField, self).clean(value) 
     79        if not self.required and value in EMPTY_VALUES: 
     80            return u'' 
    7981        try: 
    8082            return int(value) 
     
    171173        if value in EMPTY_VALUES: value = u'' 
    172174        value = smart_unicode(value) 
     175        if not self.required and value == u'': 
     176            return value 
    173177        if not self.regex.search(value): 
    174178            raise ValidationError(self.error_message) 
     
    247251        if value in EMPTY_VALUES: value = u'' 
    248252        value = smart_unicode(value) 
     253        if not self.required and value == u'': 
     254            return value 
    249255        valid_values = set([str(k) for k, v in self.choices]) 
    250256        if value not in valid_values: 
     
    260266        Validates that the input is a list or tuple. 
    261267        """ 
     268        if self.required and not value: 
     269            raise ValidationError(u'This field is required.') 
     270        elif not self.required and not value: 
     271            return [] 
    262272        if not isinstance(value, (list, tuple)): 
    263273            raise ValidationError(u'Enter a list of values.') 
    264         if self.required and not value: 
    265             raise ValidationError(u'This field is required.') 
    266274        new_value = [] 
    267275        for val in value: 
     
    278286    def __init__(self, fields=(), required=True, widget=None): 
    279287        Field.__init__(self, required, widget) 
     288        # Set 'required' to False on the individual fields, because the 
     289        # required validation will be handled by ComboField, not by those 
     290        # individual fields. 
     291        for f in fields: 
     292            f.required = False 
    280293        self.fields = fields 
    281294 
  • django/branches/multiple-db-support/django/newforms/forms.py

    r4158 r4159  
    44 
    55from django.utils.datastructures import SortedDict 
     6from django.utils.html import escape 
    67from fields import Field 
    7 from widgets import TextInput, Textarea 
     8from widgets import TextInput, Textarea, HiddenInput 
    89from util import ErrorDict, ErrorList, ValidationError 
    910 
     
    3738 
    3839    def __init__(self, data=None, auto_id=False): # TODO: prefix stuff 
     40        self.ignore_errors = data is None 
    3941        self.data = data or {} 
    4042        self.auto_id = auto_id 
     
    5759        return BoundField(self, field, name) 
    5860 
    59     def clean(self): 
    60         if self.__errors is None: 
    61             self.full_clean() 
    62         return self.clean_data 
    63  
    64     def errors(self): 
     61    def _errors(self): 
    6562        "Returns an ErrorDict for self.data" 
    6663        if self.__errors is None: 
    6764            self.full_clean() 
    6865        return self.__errors 
     66    errors = property(_errors) 
    6967 
    7068    def is_valid(self): 
    7169        """ 
    72         Returns True if the form has no errors. Otherwise, False. This exists 
    73         solely for convenience, so client code can use positive logic rather 
    74         than confusing negative logic ("if not form.errors()"). 
    75         """ 
    76         return not bool(self.errors()) 
     70        Returns True if the form has no errors. Otherwise, False. If errors are 
     71        being ignored, returns False. 
     72        """ 
     73        return not self.ignore_errors and not bool(self.errors) 
    7774 
    7875    def as_table(self): 
    7976        "Returns this form rendered as HTML <tr>s -- excluding the <table></table>." 
    80         return u'\n'.join(['<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()]) 
     77        output = [] 
     78        if self.errors.get(NON_FIELD_ERRORS): 
     79            # Errors not corresponding to a particular field are displayed at the top. 
     80            output.append(u'<tr><td colspan="2">%s</td></tr>' % self.non_field_errors()) 
     81        for name, field in self.fields.items(): 
     82            bf = BoundField(self, field, name) 
     83            if bf.is_hidden: 
     84                if bf.errors: 
     85                    new_errors = ErrorList(['(Hidden field %s) %s' % (name, e) for e in bf.errors]) 
     86                    output.append(u'<tr><td colspan="2">%s</td></tr>' % new_errors) 
     87                output.append(str(bf)) 
     88            else: 
     89                if bf.errors: 
     90                    output.append(u'<tr><td colspan="2">%s</td></tr>' % bf.errors) 
     91                output.append(u'<tr><td>%s</td><td>%s</td></tr>' % (bf.label_tag(escape(bf.verbose_name+':')), bf)) 
     92        return u'\n'.join(output) 
    8193 
    8294    def as_ul(self): 
    8395        "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>." 
    84         return u'\n'.join(['<li>%s: %s</li>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()]) 
    85  
    86     def as_table_with_errors(self): 
    87         "Returns this form rendered as HTML <tr>s, with errors." 
    8896        output = [] 
    89         if self.errors().get(NON_FIELD_ERRORS): 
     97        if self.errors.get(NON_FIELD_ERRORS): 
    9098            # Errors not corresponding to a particular field are displayed at the top. 
    91             output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]])) 
     99            output.append(u'<li>%s</li>' % self.non_field_errors()) 
    92100        for name, field in self.fields.items(): 
    93101            bf = BoundField(self, field, name) 
    94             if bf.errors: 
    95                 output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors])) 
    96             output.append('<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), bf)) 
     102            if bf.is_hidden: 
     103                if bf.errors: 
     104                    new_errors = ErrorList(['(Hidden field %s) %s' % (name, e) for e in bf.errors]) 
     105                    output.append(u'<li>%s</li>' % new_errors) 
     106                output.append(str(bf)) 
     107            else: 
     108                output.append(u'<li>%s%s %s</li>' % (bf.errors, bf.label_tag(escape(bf.verbose_name+':')), bf)) 
    97109        return u'\n'.join(output) 
    98110 
    99     def as_ul_with_errors(self): 
    100         "Returns this form rendered as HTML <li>s, with errors." 
    101         output = [] 
    102         if self.errors().get(NON_FIELD_ERRORS): 
    103             # Errors not corresponding to a particular field are displayed at the top. 
    104             output.append('<li><ul>%s</ul></li>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]])) 
    105         for name, field in self.fields.items(): 
    106             bf = BoundField(self, field, name) 
    107             line = '<li>' 
    108             if bf.errors: 
    109                 line += '<ul>%s</ul>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors]) 
    110             line += '%s: %s</li>' % (pretty_name(name), bf) 
    111             output.append(line) 
    112         return u'\n'.join(output) 
     111    def non_field_errors(self): 
     112        """ 
     113        Returns an ErrorList of errors that aren't associated with a particular 
     114        field -- i.e., from Form.clean(). Returns an empty ErrorList if there 
     115        are none. 
     116        """ 
     117        return self.errors.get(NON_FIELD_ERRORS, ErrorList()) 
    113118 
    114119    def full_clean(self): 
     
    118123        self.clean_data = {} 
    119124        errors = ErrorDict() 
    120         for name, field in self.fields.items(): 
    121             value = self.data.get(name, None) 
     125        if self.ignore_errors: # Stop further processing. 
     126            self.__errors = errors 
     127            return 
     128        for name, field in self.fields.items(): 
     129            # value_from_datadict() gets the data from the dictionary. 
     130            # Each widget type knows how to retrieve its own data, because some 
     131            # widgets split data over several HTML fields. 
     132            value = field.widget.value_from_datadict(self.data, name) 
    122133            try: 
    123134                value = field.clean(value) 
     
    139150        """ 
    140151        Hook for doing any extra form-wide cleaning after Field.clean() been 
    141         called on every field. 
     152        called on every field. Any ValidationError raised by this method will 
     153        not be associated with a particular field; it will have a special-case 
     154        association with the field named '__all__'. 
    142155        """ 
    143156        return self.clean_data 
     
    154167        # Use the 'widget' attribute on the field to determine which type 
    155168        # of HTML widget to use. 
    156         return self.as_widget(self._field.widget) 
     169        value = self.as_widget(self._field.widget) 
     170        if not isinstance(value, basestring): 
     171            # Some Widget render() methods -- notably RadioSelect -- return a 
     172            # "special" object rather than a string. Call the __str__() on that 
     173            # object to get its rendered value. 
     174            value = value.__str__() 
     175        return value 
    157176 
    158177    def _errors(self): 
     
    162181        """ 
    163182        try: 
    164             return self._form.errors()[self._name] 
     183            return self._form.errors[self._name] 
    165184        except KeyError: 
    166185            return ErrorList() 
     
    170189        attrs = attrs or {} 
    171190        auto_id = self.auto_id 
    172         if not attrs.has_key('id') and not widget.attrs.has_key('id') and auto_id
     191        if auto_id and not attrs.has_key('id') and not widget.attrs.has_key('id')
    173192            attrs['id'] = auto_id 
    174         return widget.render(self._name, self._form.data.get(self._name, None), attrs=attrs) 
     193        return widget.render(self._name, self.data, attrs=attrs) 
    175194 
    176195    def as_text(self, attrs=None): 
     
    183202        "Returns a string of HTML for representing this as a <textarea>." 
    184203        return self.as_widget(Textarea(), attrs) 
     204 
     205    def as_hidden(self, attrs=None): 
     206        """ 
     207        Returns a string of HTML for representing this as an <input type="hidden">. 
     208        """ 
     209        return self.as_widget(HiddenInput(), attrs) 
     210 
     211    def _data(self): 
     212        "Returns the data for this BoundField, or None if it wasn't given." 
     213        return self._form.data.get(self._name, None) 
     214    data = property(_data) 
     215 
     216    def _verbose_name(self): 
     217        return pretty_name(self._name) 
     218    verbose_name = property(_verbose_name) 
     219 
     220    def label_tag(self, contents=None): 
     221        """ 
     222        Wraps the given contents in a <label>, if the field has an ID attribute. 
     223        Does not HTML-escape the contents. If contents aren't given, uses the 
     224        field's HTML-escaped verbose_name. 
     225        """ 
     226        contents = contents or escape(self.verbose_name) 
     227        widget = self._field.widget 
     228        id_ = widget.attrs.get('id') or self.auto_id 
     229        if id_: 
     230            contents = '<label for="%s">%s</label>' % (widget.id_for_label(id_), contents) 
     231        return contents 
     232 
     233    def _is_hidden(self): 
     234        "Returns True if this BoundField's widget is hidden." 
     235        return self._field.widget.is_hidden 
     236    is_hidden = property(_is_hidden) 
    185237 
    186238    def _auto_id(self): 
  • django/branches/multiple-db-support/django/newforms/__init__.py

    r4156 r4159  
    1515from fields import * 
    1616from forms import Form 
    17  
    18 ########################## 
    19 # DATABASE API SHORTCUTS # 
    20 ########################## 
    21  
    22 def form_for_model(model): 
    23     "Returns a Form instance for the given Django model class." 
    24     raise NotImplementedError 
    25  
    26 def form_for_fields(field_list): 
    27     "Returns a Form instance for the given list of Django database field instances." 
    28     raise NotImplementedError 
     17from models import * 
  • django/branches/multiple-db-support/django/newforms/widgets.py

    r4158 r4159  
    66    'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'FileInput', 
    77    'Textarea', 'CheckboxInput', 
    8     'Select', 'SelectMultiple', 'RadioSelect', 
     8    'Select', 'SelectMultiple', 'RadioSelect', 'CheckboxSelectMultiple', 
    99) 
    1010 
     
    2424class Widget(object): 
    2525    requires_data_list = False # Determines whether render()'s 'value' argument should be a list. 
     26    is_hidden = False          # Determines whether this corresponds to an <input type="hidden">. 
     27 
    2628    def __init__(self, attrs=None): 
    2729        self.attrs = attrs or {} 
     
    3133 
    3234    def build_attrs(self, extra_attrs=None, **kwargs): 
     35        "Helper function for building an attribute dictionary." 
    3336        attrs = dict(self.attrs, **kwargs) 
    3437        if extra_attrs: 
    3538            attrs.update(extra_attrs) 
    3639        return attrs 
     40 
     41    def value_from_datadict(self, data, name): 
     42        """ 
     43        Given a dictionary of data and this widget's name, returns the value 
     44        of this widget. Returns None if it's not provided. 
     45        """ 
     46        return data.get(name, None) 
     47 
     48    def id_for_label(self, id_): 
     49        """ 
     50        Returns the HTML ID attribute of this Widget for use by a <label>, 
     51        given the ID of the field. Returns None if no ID is available. 
     52 
     53        This hook is necessary because some widgets have multiple HTML 
     54        elements and, thus, multiple IDs. In that case, this method should 
     55        return an ID value that corresponds to the first ID in the widget's 
     56        tags. 
     57        """ 
     58        return id_ 
     59    id_for_label = classmethod(id_for_label) 
    3760 
    3861class Input(Widget): 
     
    5679class HiddenInput(Input): 
    5780    input_type = 'hidden' 
     81    is_hidden = True 
    5882 
    5983class FileInput(Input): 
     
    6892 
    6993class CheckboxInput(Widget): 
     94    def __init__(self, attrs=None, check_test=bool): 
     95        # check_test is a callable that takes a value and returns True 
     96        # if the checkbox should be checked for that value. 
     97        self.attrs = attrs or {} 
     98        self.check_test = check_test 
     99 
    70100    def render(self, name, value, attrs=None): 
    71101        final_attrs = self.build_attrs(attrs, type='checkbox', name=name) 
    72         if value: final_attrs['checked'] = 'checked' 
     102        try: 
     103            result = self.check_test(value) 
     104        except: # Silently catch exceptions 
     105            result = False 
     106        if result: 
     107            final_attrs['checked'] = 'checked' 
     108        if value not in ('', True, False, None): 
     109            final_attrs['value'] = smart_unicode(value) # Only add the 'value' attribute if a value is non-empty. 
    73110        return u'<input%s />' % flatatt(final_attrs) 
    74111 
     
    112149class RadioInput(object): 
    113150    "An object used by RadioFieldRenderer that represents a single <input type='radio'>." 
    114     def __init__(self, name, value, attrs, choice): 
     151    def __init__(self, name, value, attrs, choice, index): 
    115152        self.name, self.value = name, value 
    116         self.attrs = attrs or {} 
     153        self.attrs = attrs 
    117154        self.choice_value, self.choice_label = choice 
     155        self.index = index 
    118156 
    119157    def __str__(self): 
     
    124162 
    125163    def tag(self): 
     164        if self.attrs.has_key('id'): 
     165            self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index) 
    126166        final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value) 
    127167        if self.is_checked(): 
     
    136176 
    137177    def __iter__(self): 
    138         for choice in self.choices
    139             yield RadioInput(self.name, self.value, self.attrs, choice
     178        for i, choice in enumerate(self.choices)
     179            yield RadioInput(self.name, self.value, self.attrs.copy(), choice, i
    140180 
    141181    def __str__(self): 
     
    148188        if value is None: value = '' 
    149189        str_value = smart_unicode(value) # Normalize to string. 
     190        attrs = attrs or {} 
    150191        return RadioFieldRenderer(name, str_value, attrs, list(chain(self.choices, choices))) 
    151192 
    152 class CheckboxSelectMultiple(Widget): 
    153     pass 
     193    def id_for_label(self, id_): 
     194        # RadioSelect is represented by multiple <input type="radio"> fields, 
     195        # each of which has a distinct ID. The IDs are made distinct by a "_X" 
     196        # suffix, where X is the zero-based index of the radio field. Thus, 
     197        # the label for a RadioSelect should reference the first one ('_0'). 
     198        if id_: 
     199            id_ += '_0' 
     200        return id_ 
     201    id_for_label = classmethod(id_for_label) 
     202 
     203class CheckboxSelectMultiple(SelectMultiple): 
     204    def render(self, name, value, attrs=None, choices=()): 
     205        if value is None: value = [] 
     206        final_attrs = self.build_attrs(attrs, name=name) 
     207        output = [u'<ul>'] 
     208        str_values = set([smart_unicode(v) for v in value]) # Normalize to strings. 
     209        cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values) 
     210        for option_value, option_label in chain(self.choices, choices): 
     211            option_value = smart_unicode(option_value) 
     212            rendered_cb = cb.render(name, option_value) 
     213            output.append(u'<li><label>%s %s</label></li>' % (rendered_cb, escape(smart_unicode(option_label)))) 
     214        output.append(u'</ul>') 
     215        return u'\n'.join(output) 
     216 
     217    def id_for_label(self, id_): 
     218        # See the comment for RadioSelect.id_for_label() 
     219        if id_: 
     220            id_ += '_0' 
     221        return id_ 
     222    id_for_label = classmethod(id_for_label) 
  • django/branches/multiple-db-support/django/views/generic/list_detail.py

    r3071 r4159  
    8585        mimetype=None): 
    8686    """ 
    87     Generic list of objects
     87    Generic detail of an object
    8888 
    8989    Templates: ``<app_label>/<model_name>_detail.html`` 
  • django/branches/multiple-db-support/docs/sessions.txt

    r3581 r4159  
    142142 
    143143    def login(request): 
    144         if request.POST
     144        if request.method == 'POST'
    145145            if request.session.test_cookie_worked(): 
    146146                request.session.delete_test_cookie() 
  • django/branches/multiple-db-support/docs/testing.txt

    r4158 r4159  
    134134 
    135135For developers new to testing, however, this choice can seem 
    136 confusing, so here are a few key differences to help you decide weather 
     136confusing, so here are a few key differences to help you decide whether 
    137137doctests or unit tests are right for you. 
    138138 
  • django/branches/multiple-db-support/setup.py

    r4155 r4159  
    1212# an easy way to do this. 
    1313packages, data_files = [], [] 
    14 root_dir = os.path.join(os.path.dirname(__file__), 'django') 
    15 for dirpath, dirnames, filenames in os.walk(root_dir): 
     14root_dir = os.path.dirname(__file__) 
     15len_root_dir = len(root_dir) 
     16django_dir = os.path.join(root_dir, 'django') 
     17 
     18for dirpath, dirnames, filenames in os.walk(django_dir): 
    1619    # Ignore dirnames that start with '.' 
    1720    for i, dirname in enumerate(dirnames): 
    1821        if dirname.startswith('.'): del dirnames[i] 
    1922    if '__init__.py' in filenames: 
    20         packages.append(dirpath.replace('/', '.')) 
     23        package = dirpath[len_root_dir:].lstrip('/').replace('/', '.') 
     24        packages.append(package) 
    2125    else: 
    2226        data_files.append((dirpath, [os.path.join(dirpath, f) for f in filenames])) 
  • django/branches/multiple-db-support/tests/regressiontests/forms/tests.py

    r4158 r4159  
    44>>> import datetime 
    55>>> import re 
     6 
     7########### 
     8# Widgets # 
     9########### 
     10 
     11Each Widget class corresponds to an HTML form widget. A Widget knows how to 
     12render itself, given a field name and some data. Widgets don't perform 
     13validation. 
    614 
    715# TextInput Widget ############################################################ 
     
    157165>>> w.render('is_cool', '') 
    158166u'<input type="checkbox" name="is_cool" />' 
     167>>> w.render('is_cool', None) 
     168u'<input type="checkbox" name="is_cool" />' 
    159169>>> w.render('is_cool', False) 
    160170u'<input type="checkbox" name="is_cool" />' 
    161171>>> w.render('is_cool', True) 
    162172u'<input checked="checked" type="checkbox" name="is_cool" />' 
     173 
     174Using any value that's not in ('', None, False, True) will check the checkbox 
     175and set the 'value' attribute. 
     176>>> w.render('is_cool', 'foo') 
     177u'<input checked="checked" type="checkbox" name="is_cool" value="foo" />' 
     178 
    163179>>> w.render('is_cool', False, attrs={'class': 'pretty'}) 
    164180u'<input type="checkbox" name="is_cool" class="pretty" />' 
     
    173189>>> w.render('is_cool', '', attrs={'class': 'special'}) 
    174190u'<input type="checkbox" class="special" name="is_cool" />' 
     191 
     192You can pass 'check_test' to the constructor. This is a callable that takes the 
     193value and returns True if the box should be checked. 
     194>>> w = CheckboxInput(check_test=lambda value: value.startswith('hello')) 
     195>>> w.render('greeting', '') 
     196u'<input type="checkbox" name="greeting" />' 
     197>>> w.render('greeting', 'hello') 
     198u'<input checked="checked" type="checkbox" name="greeting" value="hello" />' 
     199>>> w.render('greeting', 'hello there') 
     200u'<input checked="checked" type="checkbox" name="greeting" value="hello there" />' 
     201>>> w.render('greeting', 'hello & goodbye') 
     202u'<input checked="checked" type="checkbox" name="greeting" value="hello &amp; goodbye" />' 
     203 
     204A subtlety: If the 'check_test' argument cannot handle a value and raises any 
     205exception during its __call__, then the exception will be swallowed and the box 
     206will not be checked. In this example, the 'check_test' assumes the value has a 
     207startswith() method, which fails for the values True, False and None. 
     208>>> w.render('greeting', True) 
     209u'<input type="checkbox" name="greeting" />' 
     210>>> w.render('greeting', False) 
     211u'<input type="checkbox" name="greeting" />' 
     212>>> w.render('greeting', None) 
     213u'<input type="checkbox" name="greeting" />' 
    175214 
    176215# Select Widget ############################################################### 
     
    476515beatle J R Ringo False 
    477516 
     517# CheckboxSelectMultiple Widget ############################################### 
     518 
     519>>> w = CheckboxSelectMultiple() 
     520>>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
     521<ul> 
     522<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> 
     523<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     524<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> 
     525<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
     526</ul> 
     527>>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
     528<ul> 
     529<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> 
     530<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     531<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> 
     532<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
     533</ul> 
     534>>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
     535<ul> 
     536<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> 
     537<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     538<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> 
     539<li><label><input checked="checked" type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
     540</ul> 
     541 
     542If the value is None, none of the options are selected: 
     543>>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
     544<ul> 
     545<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li> 
     546<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     547<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> 
     548<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
     549</ul> 
     550 
     551If the value corresponds to a label (but not to an option value), none of the options are selected: 
     552>>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
     553<ul> 
     554<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li> 
     555<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     556<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> 
     557<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
     558</ul> 
     559 
     560If multiple values are given, but some of them are not valid, the valid ones are selected: 
     561>>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
     562<ul> 
     563<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> 
     564<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> 
     565<li><label><input checked="checked" type="checkbox" name="beatles" value="G" /> George</label></li> 
     566<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> 
     567</ul> 
     568 
     569The value is compared to its str(): 
     570>>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')]) 
     571<ul> 
     572<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     573<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     574<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
     575</ul> 
     576>>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)]) 
     577<ul> 
     578<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     579<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     580<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
     581</ul> 
     582>>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)]) 
     583<ul> 
     584<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     585<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     586<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
     587</ul> 
     588 
     589The 'choices' argument can be any iterable: 
     590>>> def get_choices(): 
     591...     for i in range(5): 
     592...         yield (i, i) 
     593>>> print w.render('nums', [2], choices=get_choices()) 
     594<ul> 
     595<li><label><input type="checkbox" name="nums" value="0" /> 0</label></li> 
     596<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     597<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     598<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
     599<li><label><input type="checkbox" name="nums" value="4" /> 4</label></li> 
     600</ul> 
     601 
     602You can also pass 'choices' to the constructor: 
     603>>> w = CheckboxSelectMultiple(choices=[(1, 1), (2, 2), (3, 3)]) 
     604>>> print w.render('nums', [2]) 
     605<ul> 
     606<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     607<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     608<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
     609</ul> 
     610 
     611If 'choices' is passed to both the constructor and render(), then they'll both be in the output: 
     612>>> print w.render('nums', [2], choices=[(4, 4), (5, 5)]) 
     613<ul> 
     614<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> 
     615<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> 
     616<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> 
     617<li><label><input type="checkbox" name="nums" value="4" /> 4</label></li> 
     618<li><label><input type="checkbox" name="nums" value="5" /> 5</label></li> 
     619</ul> 
     620 
     621>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) 
     622u'<ul>\n<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>\n<li><label><input type="checkbox" name="nums" value="2" /> 2</label></li>\n<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>\n<li><label><input checked="checked" type="checkbox" name="nums" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="checkbox" name="nums" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>' 
     623 
     624########## 
     625# Fields # 
     626########## 
     627 
     628Each Field class does some sort of validation. Each Field has a clean() method, 
     629which either raises django.newforms.ValidationError or returns the "clean" 
     630data -- usually a Unicode object, but, in some rare cases, a list. 
     631 
     632Each Field's __init__() takes at least these parameters: 
     633    required -- Boolean that specifies whether the field is required. 
     634                True by default. 
     635    widget -- A Widget class, or instance of a Widget class, that should be 
     636              used for this Field when displaying it. Each Field has a default 
     637              Widget that it'll use if you don't specify this. In most cases, 
     638              the default widget is TextInput. 
     639 
     640Other than that, the Field subclasses have class-specific options for 
     641__init__(). For example, CharField has a max_length option. 
     642 
    478643# CharField ################################################################### 
     644 
     645>>> f = CharField() 
     646>>> f.clean(1) 
     647u'1' 
     648>>> f.clean('hello') 
     649u'hello' 
     650>>> f.clean(None) 
     651Traceback (most recent call last): 
     652... 
     653ValidationError: [u'This field is required.'] 
     654>>> f.clean('') 
     655Traceback (most recent call last): 
     656... 
     657ValidationError: [u'This field is required.'] 
     658>>> f.clean([1, 2, 3]) 
     659u'[1, 2, 3]' 
    479660 
    480661>>> f = CharField(required=False) 
     
    485666>>> f.clean(None) 
    486667u'' 
     668>>> f.clean('') 
     669u'' 
    487670>>> f.clean([1, 2, 3]) 
    488671u'[1, 2, 3]' 
     
    490673CharField accepts an optional max_length parameter: 
    491674>>> f = CharField(max_length=10, required=False) 
    492 >>> f.clean('') 
    493 u'' 
    494675>>> f.clean('12345') 
    495676u'12345' 
     
    519700 
    520701>>> f = IntegerField() 
     702>>> f.clean('') 
     703Traceback (most recent call last): 
     704... 
     705ValidationError: [u'This field is required.'] 
     706>>> f.clean(None) 
     707Traceback (most recent call last): 
     708... 
     709ValidationError: [u'This field is required.'] 
     710>>> f.clean('1') 
     7111 
     712>>> isinstance(f.clean('1'), int) 
     713True 
     714>>> f.clean('23') 
     71523 
     716>>> f.clean('a') 
     717Traceback (most recent call last): 
     718... 
     719ValidationError: [u'Enter a whole number.'] 
     720>>> f.clean('1 ') 
     7211 
     722>>> f.clean(' 1') 
     7231 
     724>>> f.clean(' 1 ') 
     7251 
     726>>> f.clean('1a') 
     727Traceback (most recent call last): 
     728... 
     729ValidationError: [u'Enter a whole number.'] 
     730 
     731>>> f = IntegerField(required=False) 
     732>>> f.clean('') 
     733u'' 
     734>>> f.clean(None) 
     735u'' 
    521736>>> f.clean('1') 
    5227371 
     
    682897ValidationError: [u'Enter a valid date/time.'] 
    683898 
     899>>> f = DateTimeField(required=False) 
     900>>> f.clean(None) 
     901>>> repr(f.clean(None)) 
     902'None' 
     903>>> f.clean('') 
     904>>> repr(f.clean('')) 
     905'None' 
     906 
    684907# RegexField ################################################################## 
    685908 
     
    701924... 
    702925ValidationError: [u'Enter a valid value.'] 
     926>>> f.clean('') 
     927Traceback (most recent call last): 
     928... 
     929ValidationError: [u'This field is required.'] 
     930 
     931>>> f = RegexField('^\d[A-F]\d$', required=False) 
     932>>> f.clean('2A2') 
     933u'2A2' 
     934>>> f.clean('3F3') 
     935u'3F3' 
     936>>> f.clean('3G3') 
     937Traceback (most recent call last): 
     938... 
     939ValidationError: [u'Enter a valid value.'] 
     940>>> f.clean('') 
     941u'' 
    703942 
    704943Alternatively, RegexField can take a compiled regular expression: 
     
    737976 
    738977>>> f = EmailField() 
     978>>> f.clean('') 
     979Traceback (most recent call last): 
     980... 
     981ValidationError: [u'This field is required.'] 
     982>>> f.clean(None) 
     983Traceback (most recent call last): 
     984... 
     985ValidationError: [u'This field is required.'] 
    739986>>> f.clean('person@example.com') 
    740987u'person@example.com' 
     
    752999ValidationError: [u'Enter a valid e-mail address.'] 
    7531000 
     1001>>> f = EmailField(required=False) 
     1002>>> f.clean('') 
     1003u'' 
     1004>>> f.clean(None) 
     1005u'' 
     1006>>> f.clean('person@example.com') 
     1007u'person@example.com' 
     1008>>> f.clean('foo') 
     1009Traceback (most recent call last): 
     1010... 
     1011ValidationError: [u'Enter a valid e-mail address.'] 
     1012>>> f.clean('foo@') 
     1013Traceback (most recent call last): 
     1014... 
     1015ValidationError: [u'Enter a valid e-mail address.'] 
     1016>>> f.clean('foo@bar') 
     1017Traceback (most recent call last): 
     1018... 
     1019ValidationError: [u'Enter a valid e-mail address.'] 
     1020 
    7541021# URLField ################################################################## 
    7551022 
    7561023>>> f = URLField() 
     1024>>> f.clean('') 
     1025Traceback (most recent call last): 
     1026... 
     1027ValidationError: [u'This field is required.'] 
     1028>>> f.clean(None) 
     1029Traceback (most recent call last): 
     1030... 
     1031ValidationError: [u'This field is required.'] 
     1032>>> f.clean('http://example.com') 
     1033u'http://example.com' 
     1034>>> f.clean('http://www.example.com') 
     1035u'http://www.example.com' 
     1036>>> f.clean('foo') 
     1037Traceback (most recent call last): 
     1038... 
     1039ValidationError: [u'Enter a valid URL.'] 
     1040>>> f.clean('example.com') 
     1041Traceback (most recent call last): 
     1042... 
     1043ValidationError: [u'Enter a valid URL.'] 
     1044>>> f.clean('http://') 
     1045Traceback (most recent call last): 
     1046... 
     1047ValidationError: [u'Enter a valid URL.'] 
     1048>>> f.clean('http://example') 
     1049Traceback (most recent call last): 
     1050... 
     1051ValidationError: [u'Enter a valid URL.'] 
     1052>>> f.clean('http://example.') 
     1053Traceback (most recent call last): 
     1054... 
     1055ValidationError: [u'Enter a valid URL.'] 
     1056>>> f.clean('http://.com') 
     1057Traceback (most recent call last): 
     1058... 
     1059ValidationError: [u'Enter a valid URL.'] 
     1060 
     1061>>> f = URLField(required=False) 
     1062>>> f.clean('') 
     1063u'' 
     1064>>> f.clean(None) 
     1065u'' 
    7571066>>> f.clean('http://example.com') 
    7581067u'http://example.com' 
     
    8051114 
    8061115>>> f = BooleanField() 
     1116>>> f.clean('') 
     1117Traceback (most recent call last): 
     1118... 
     1119ValidationError: [u'This field is required.'] 
     1120>>> f.clean(None) 
     1121Traceback (most recent call last): 
     1122... 
     1123ValidationError: [u'This field is required.'] 
    8071124>>> f.clean(True) 
    8081125True 
     
    8161133True 
    8171134 
     1135>>> f = BooleanField(required=False) 
     1136>>> f.clean('') 
     1137False 
     1138>>> f.clean(None) 
     1139False 
     1140>>> f.clean(True) 
     1141True 
     1142>>> f.clean(False) 
     1143False 
     1144>>> f.clean(1) 
     1145True 
     1146>>> f.clean(0) 
     1147False 
     1148>>> f.clean('Django rocks') 
     1149True 
     1150 
    8181151# ChoiceField ################################################################# 
    8191152 
    8201153>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')]) 
     1154>>> f.clean('') 
     1155Traceback (most recent call last): 
     1156... 
     1157ValidationError: [u'This field is required.'] 
     1158>>> f.clean(None) 
     1159Traceback (most recent call last): 
     1160... 
     1161ValidationError: [u'This field is required.'] 
    8211162>>> f.clean(1) 
    8221163u'1' 
    8231164>>> f.clean('1') 
    8241165u'1' 
     1166>>> f.clean('3') 
     1167Traceback (most recent call last): 
     1168... 
     1169ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] 
     1170 
     1171>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')], required=False) 
     1172>>> f.clean('') 
     1173u'' 
    8251174>>> f.clean(None) 
    826 Traceback (most recent call last): 
    827 ... 
    828 ValidationError: [u'This field is required.'] 
    829 >>> f.clean('') 
    830 Traceback (most recent call last): 
    831 ... 
    832 ValidationError: [u'This field is required.'] 
     1175u'' 
     1176>>> f.clean(1) 
     1177u'1' 
     1178>>> f.clean('1') 
     1179u'1' 
    8331180>>> f.clean('3') 
    8341181Traceback (most recent call last): 
     
    8471194 
    8481195>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')]) 
     1196>>> f.clean('') 
     1197Traceback (most recent call last): 
     1198... 
     1199ValidationError: [u'This field is required.'] 
     1200>>> f.clean(None) 
     1201Traceback (most recent call last): 
     1202... 
     1203ValidationError: [u'This field is required.'] 
    8491204>>> f.clean([1]) 
    8501205[u'1'] 
     
    8741229ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] 
    8751230 
     1231>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')], required=False) 
     1232>>> f.clean('') 
     1233[] 
     1234>>> f.clean(None) 
     1235[] 
     1236>>> f.clean([1]) 
     1237[u'1'] 
     1238>>> f.clean(['1']) 
     1239[u'1'] 
     1240>>> f.clean(['1', '2']) 
     1241[u'1', u'2'] 
     1242>>> f.clean([1, '2']) 
     1243[u'1', u'2'] 
     1244>>> f.clean((1, '2')) 
     1245[u'1', u'2'] 
     1246>>> f.clean('hello') 
     1247Traceback (most recent call last): 
     1248... 
     1249ValidationError: [u'Enter a list of values.'] 
     1250>>> f.clean([]) 
     1251[] 
     1252>>> f.clean(()) 
     1253[] 
     1254>>> f.clean(['3']) 
     1255Traceback (most recent call last): 
     1256... 
     1257ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] 
     1258 
    8761259# ComboField ################################################################## 
    8771260 
    8781261ComboField takes a list of fields that should be used to validate a value, 
    879 in that order: 
     1262in that order. 
    8801263>>> f = ComboField(fields=[CharField(max_length=20), EmailField()]) 
    8811264>>> f.clean('test@example.com') 
     
    8981281ValidationError: [u'This field is required.'] 
    8991282 
     1283>>> f = ComboField(fields=[CharField(max_length=20), EmailField()], required=False) 
     1284>>> f.clean('test@example.com') 
     1285u'test@example.com' 
     1286>>> f.clean('longemailaddress@example.com') 
     1287Traceback (most recent call last): 
     1288... 
     1289ValidationError: [u'Ensure this value has at most 20 characters.'] 
     1290>>> f.clean('not an e-mail') 
     1291Traceback (most recent call last): 
     1292... 
     1293ValidationError: [u'Enter a valid e-mail address.'] 
     1294>>> f.clean('') 
     1295u'' 
     1296>>> f.clean(None) 
     1297u'' 
     1298 
     1299######### 
     1300# Forms # 
     1301######### 
     1302 
     1303A Form is a collection of Fields. It knows how to validate a set of data and it 
     1304knows how to render itself in a couple of default ways (e.g., an HTML table). 
     1305You can pass it data in __init__(), as a dictionary. 
     1306 
    9001307# Form ######################################################################## 
    9011308 
     
    9041311...     last_name = CharField() 
    9051312...     birthday = DateField() 
     1313 
     1314Pass a dictionary to a Form's __init__(). 
     1315>>> p = Person({'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9'}) 
     1316>>> p.errors 
     1317{} 
     1318>>> p.is_valid() 
     1319True 
     1320>>> p.errors.as_ul() 
     1321u'' 
     1322>>> p.errors.as_text() 
     1323u'' 
     1324>>> p.clean_data 
     1325{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} 
     1326>>> print p['first_name'] 
     1327<input type="text" name="first_name" value="John" /> 
     1328>>> print p['last_name'] 
     1329<input type="text" name="last_name" value="Lennon" /> 
     1330>>> print p['birthday'] 
     1331<input type="text" name="birthday" value="1940-10-9" /> 
     1332>>> for boundfield in p: 
     1333...     print boundfield 
     1334<input type="text" name="first_name" value="John" /> 
     1335<input type="text" name="last_name" value="Lennon" /> 
     1336<input type="text" name="birthday" value="1940-10-9" /> 
     1337>>> for boundfield in p: 
     1338...     print boundfield.verbose_name, boundfield.data 
     1339First name John 
     1340Last name Lennon 
     1341Birthday 1940-10-9 
     1342>>> print p 
     1343<tr><td>First name:</td><td><input type="text" name="first_name" value="John" /></td></tr> 
     1344<tr><td>Last name:</td><td><input type="text" name="last_name" value="Lennon" /></td></tr> 
     1345<tr><td>Birthday:</td><td><input type="text" name="birthday" value="1940-10-9" /></td></tr> 
     1346 
     1347Empty dictionaries are valid, too. 
     1348>>> p = Person({}) 
     1349>>> p.errors 
     1350{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} 
     1351>>> p.is_valid() 
     1352False 
     1353>>> print p 
     1354<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
     1355<tr><td>First name:</td><td><input type="text" name="first_name" /></td></tr> 
     1356<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
     1357<tr><td>Last name:</td><td><input type="text" name="last_name" /></td></tr> 
     1358<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
     1359<tr><td>Birthday:</td><td><input type="text" name="birthday" /></td></tr> 
     1360>>> print p.as_table() 
     1361<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
     1362<tr><td>First name:</td><td><input type="text" name="first_name" /></td></tr> 
     1363<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
     1364<tr><td>Last name:</td><td><input type="text" name="last_name" /></td></tr> 
     1365<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
     1366<tr><td>Birthday:</td><td><input type="text" name="birthday" /></td></tr> 
     1367>>> print p.as_ul() 
     1368<li><ul class="errorlist"><li>This field is required.</li></ul>First name: <input type="text" name="first_name" /></li> 
     1369<li><ul class="errorlist"><li>This field is required.</li></ul>Last name: <input type="text" name="last_name" /></li> 
     1370<li><ul class="errorlist"><li>This field is required.</li></ul>Birthday: <input type="text" name="birthday" /></li> 
     1371 
     1372If you don't pass any values to the Form's __init__(), or if you pass None, 
     1373the Form won't do any validation. Form.errors will be an empty dictionary *but* 
     1374Form.is_valid() will return False. 
    9061375>>> p = Person() 
     1376>>> p.errors 
     1377{} 
     1378>>> p.is_valid() 
     1379False 
    9071380>>> print p 
    9081381<tr><td>First name:</td><td><input type="text" name="first_name" /></td></tr> 
     
    9171390<li>Last name: <input type="text" name="last_name" /></li> 
    9181391<li>Birthday: <input type="text" name="birthday" /></li> 
    919 >>> print p.as_table_with_errors() 
    920 <tr><td colspan="2"><ul><li>This field is required.</li></ul></td></tr> 
    921 <tr><td>First name:</td><td><input type="text" name="first_name" /></td></tr> 
    922 <tr><td colspan="2"><ul><li>This field is required.</li></ul></td></tr> 
    923 <tr><td>Last name:</td><td><input type="text" name="last_name" /></td></tr> 
    924 <tr><td colspan="2"><ul><li>This field is required.</li></ul></td></tr> 
    925 <tr><td>Birthday:</td><td><input type="text" name="birthday" /></td></tr> 
    926 >>> print p.as_ul_with_errors() 
    927 <li><ul><li>This field is required.</li></ul>First name: <input type="text" name="first_name" /></li> 
    928 <li><ul><li>This field is required.</li></ul>Last name: <input type="text" name="last_name" /></li> 
    929 <li><ul><li>This field is required.</li></ul>Birthday: <input type="text" name="birthday" /></li> 
    930  
    931 >>> p = Person({'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9'}) 
    932 >>> p.errors() 
    933 {} 
    934 >>> p.is_valid() 
    935 True 
    936 >>> p.errors().as_ul() 
    937 u'' 
    938 >>> p.errors().as_text() 
    939 u'' 
    940 >>> p.clean() 
    941 {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} 
    942 >>> print p['first_name'] 
    943 <input type="text" name="first_name" value="John" /> 
    944 >>> print p['last_name'] 
    945 <input type="text" name="last_name" value="Lennon" /> 
    946 >>> print p['birthday'] 
    947 <input type="text" name="birthday" value="1940-10-9" /> 
    948 >>> for boundfield in p: 
    949 ...     print boundfield 
    950 <input type="text" name="first_name" value="John" /> 
    951 <input type="text" name="last_name" value="Lennon" /> 
    952 <input type="text" name="birthday" value="1940-10-9" /> 
    953 >>> print p 
    954 <tr><td>First name:</td><td><input type="text" name="first_name" value="John" /></td></tr> 
    955 <tr><td>Last name:</td><td><input type="text" name="last_name" value="Lennon" /></td></tr> 
    956 <tr><td>Birthday:</td><td><input type="text" name="birthday" value="1940-10-9" /></td></tr> 
     1392 
     1393Unicode values are handled properly. 
     1394>>> p = Person({'first_name': u'John', 'last_name': u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111', 'birthday': '1940-10-9'}) 
     1395>>> p.as_table() 
     1396u'<tr><td>First name:</td><td><input type="text" name="first_name" value="John" /></td></tr>\n<tr><td>Last name:</td><td><input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /></td></tr>\n<tr><td>Birthday:</td><td><input type="text" name="birthday" value="1940-10-9" /></td></tr>' 
     1397>>> p.as_ul() 
     1398u'<li>First name: <input type="text" name="first_name" value="John" /></li>\n<li>Last name: <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /></li>\n<li>Birthday: <input type="text" name="birthday" value="1940-10-9" /></li>' 
    9571399 
    9581400>>> p = Person({'last_name': u'Lennon'}) 
    959 >>> p.errors() 
     1401>>> p.errors 
    9601402{'first_name': [u'This field is required.'], 'birthday': [u'This field is required.']} 
    9611403>>> p.is_valid() 
    9621404False 
    963 >>> p.errors().as_ul() 
     1405>>> p.errors.as_ul() 
    9641406u'<ul class="errorlist"><li>first_name<ul class="errorlist"><li>This field is required.</li></ul></li><li>birthday<ul class="errorlist"><li>This field is required.</li></ul></li></ul>' 
    965 >>> print p.errors().as_text() 
     1407>>> print p.errors.as_text() 
    9661408* first_name 
    9671409  * This field is required. 
    9681410* birthday 
    9691411  * This field is required. 
    970 >>> p.clean() 
    971 >>> repr(p.clean()
     1412>>> p.clean_data 
     1413>>> repr(p.clean_data
    9721414'None' 
    9731415>>> p['first_name'].errors 
     
    9881430"auto_id" tells the Form to add an "id" attribute to each form element. 
    9891431If it's a string that contains '%s', Django will use that as a format string 
    990 into which the field's name will be inserted. 
     1432into which the field's name will be inserted. It will also put a <label> around 
     1433the human-readable labels for a field. 
    9911434>>> p = Person(auto_id='id_%s') 
    9921435>>> print p.as_ul() 
    993 <li>First name: <input type="text" name="first_name" id="id_first_name" /></li> 
    994 <li>Last name: <input type="text" name="last_name" id="id_last_name" /></li> 
    995 <li>Birthday: <input type="text" name="birthday" id="id_birthday" /></li> 
     1436<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li> 
     1437<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li> 
     1438<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li> 
     1439>>> print p.as_table() 
     1440<tr><td><label for="id_first_name">First name:</label></td><td><input type="text" name="first_name" id="id_first_name" /></td></tr> 
     1441<tr><td><label for="id_last_name">Last name:</label></td><td><input type="text" name="last_name" id="id_last_name" /></td></tr> 
     1442<tr><td><label for="id_birthday">Birthday:</label></td><td><input type="text" name="birthday" id="id_birthday" /></td></tr> 
    9961443 
    9971444If auto_id is any True value whose str() does not contain '%s', the "id" 
     
    9991446>>> p = Person(auto_id=True) 
    10001447>>> print p.as_ul() 
    1001 <li>First name: <input type="text" name="first_name" id="first_name" /></li> 
    1002 <li>Last name: <input type="text" name="last_name" id="last_name" /></li> 
    1003 <li>Birthday: <input type="text" name="birthday" id="birthday" /></li> 
     1448<li><label for="first_name">First name:</label> <input type="text" name="first_name" id="first_name" /></li> 
     1449<li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li> 
     1450<li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li> 
    10041451 
    10051452If auto_id is any False value, an "id" attribute won't be output unless it 
     
    10121459 
    10131460In this example, auto_id is False, but the "id" attribute for the "first_name" 
    1014 field is given. 
     1461field is given. Also note that field gets a <label>, while the others don't. 
    10151462>>> class PersonNew(Form): 
    10161463...     first_name = CharField(widget=TextInput(attrs={'id': 'first_name_id'})) 
     
    10191466>>> p = PersonNew(auto_id=False) 
    10201467>>> print p.as_ul() 
    1021 <li>First name: <input type="text" id="first_name_id" name="first_name" /></li> 
     1468<li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li> 
    10221469<li>Last name: <input type="text" name="last_name" /></li> 
    10231470<li>Birthday: <input type="text" name="birthday" /></li> 
     
    10271474>>> p = PersonNew(auto_id=True) 
    10281475>>> print p.as_ul() 
    1029 <li>First name: <input type="text" id="first_name_id" name="first_name" /></li> 
    1030 <li>Last name: <input type="text" name="last_name" id="last_name" /></li> 
    1031 <li>Birthday: <input type="text" name="birthday" id="birthday" /></li> 
     1476<li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li> 
     1477<li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li> 
     1478<li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li> 
    10321479 
    10331480>>> class SignupForm(Form): 
     
    10561503<textarea name="message"></textarea> 
    10571504 
    1058 as_textarea() and as_text() are shortcuts for changing the output widget type: 
     1505as_textarea(), as_text() and as_hidden() are shortcuts for changing the output 
     1506widget type: 
    10591507>>> f['subject'].as_textarea() 
    10601508u'<textarea name="subject"></textarea>' 
    10611509>>> f['message'].as_text() 
    10621510u'<input type="text" name="message" />' 
     1511>>> f['message'].as_hidden() 
     1512u'<input type="hidden" name="message" />' 
    10631513 
    10641514The 'widget' parameter to a Field can also be an instance: 
     
    10701520<textarea rows="80" cols="20" name="message"></textarea> 
    10711521 
    1072 Instance-level attrs are *not* carried over to as_textarea() and as_text(): 
     1522Instance-level attrs are *not* carried over to as_textarea(), as_text() and 
     1523as_hidden(): 
    10731524>>> f['message'].as_text() 
    10741525u'<input type="text" name="message" />' 
     
    10781529>>> f['message'].as_text() 
    10791530u'<input type="text" name="message" value="I love you." />' 
     1531>>> f['message'].as_hidden() 
     1532u'<input type="hidden" name="message" value="I love you." />' 
    10801533 
    10811534For a form with a <select>, use ChoiceField: 
     
    10961549</select> 
    10971550 
     1551Add widget=RadioSelect to use that widget with a ChoiceField. 
     1552>>> class FrameworkForm(Form): 
     1553...     name = CharField() 
     1554...     language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=RadioSelect) 
     1555>>> f = FrameworkForm() 
     1556>>> print f['language'] 
     1557<ul> 
     1558<li><label><input type="radio" name="language" value="P" /> Python</label></li> 
     1559<li><label><input type="radio" name="language" value="J" /> Java</label></li> 
     1560</ul> 
     1561>>> print f 
     1562<tr><td>Name:</td><td><input type="text" name="name" /></td></tr> 
     1563<tr><td>Language:</td><td><ul> 
     1564<li><label><input type="radio" name="language" value="P" /> Python</label></li> 
     1565<li><label><input type="radio" name="language" value="J" /> Java</label></li> 
     1566</ul></td></tr> 
     1567>>> print f.as_ul() 
     1568<li>Name: <input type="text" name="name" /></li> 
     1569<li>Language: <ul> 
     1570<li><label><input type="radio" name="language" value="P" /> Python</label></li> 
     1571<li><label><input type="radio" name="language" value="J" /> Java</label></li> 
     1572</ul></li> 
     1573 
     1574Regarding auto_id and <label>, RadioSelect is a special case. Each radio button 
     1575gets a distinct ID, formed by appending an underscore plus the button's 
     1576zero-based index. 
     1577>>> f = FrameworkForm(auto_id='id_%s') 
     1578>>> print f['language'] 
     1579<ul> 
     1580<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> 
     1581<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> 
     1582</ul> 
     1583 
     1584When RadioSelect is used with auto_id, and the whole form is printed using 
     1585either as_table() or as_ul(), the label for the RadioSelect will point to the 
     1586ID of the *first* radio button. 
     1587>>> print f 
     1588<tr><td><label for="id_name">Name:</label></td><td><input type="text" name="name" id="id_name" /></td></tr> 
     1589<tr><td><label for="id_language_0">Language:</label></td><td><ul> 
     1590<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> 
     1591<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> 
     1592</ul></td></tr> 
     1593>>> print f.as_ul() 
     1594<li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></li> 
     1595<li><label for="id_language_0">Language:</label> <ul> 
     1596<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> 
     1597<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> 
     1598</ul></li> 
     1599 
    10981600MultipleChoiceField is a special case, as its data is required to be a list: 
    10991601>>> class SongForm(Form): 
     
    11221624</select> 
    11231625 
     1626MultipleChoiceField can also be used with the CheckboxSelectMultiple widget. 
     1627>>> class SongForm(Form): 
     1628...     name = CharField() 
     1629...     composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=CheckboxSelectMultiple) 
     1630>>> f = SongForm() 
     1631>>> print f['composers'] 
     1632<ul> 
     1633<li><label><input type="checkbox" name="composers" value="J" /> John Lennon</label></li> 
     1634<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> 
     1635</ul> 
     1636>>> f = SongForm({'composers': ['J']}) 
     1637>>> print f['composers'] 
     1638<ul> 
     1639<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li> 
     1640<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> 
     1641</ul> 
     1642>>> f = SongForm({'composers': ['J', 'P']}) 
     1643>>> print f['composers'] 
     1644<ul> 
     1645<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li> 
     1646<li><label><input checked="checked" type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> 
     1647</ul> 
     1648 
     1649When using CheckboxSelectMultiple, the framework expects a list of input and 
     1650returns a list of input. 
     1651>>> f = SongForm({'name': 'Yesterday'}) 
     1652>>> f.errors 
     1653{'composers': [u'This field is required.']} 
     1654>>> f = SongForm({'name': 'Yesterday', 'composers': ['J']}) 
     1655>>> f.errors 
     1656{} 
     1657>>> f.clean_data 
     1658{'composers': [u'J'], 'name': u'Yesterday'} 
     1659>>> f = SongForm({'name': 'Yesterday', 'composers': ['J', 'P']}) 
     1660>>> f.errors 
     1661{} 
     1662>>> f.clean_data 
     1663{'composers': [u'J', u'P'], 'name': u'Yesterday'} 
     1664 
    11241665There are a couple of ways to do multiple-field validation. If you want the 
    11251666validation message to be associated with a particular field, implement the 
    11261667clean_XXX() method on the Form, where XXX is the field name. As in 
    1127 Field.clean(), the clean_XXX() method should return the cleaned value: 
     1668Field.clean(), the clean_XXX() method should return the cleaned value. In the 
     1669clean_XXX() method, you have access to self.clean_data, which is a dictionary 
     1670of all the data that has been cleaned *so far*, in order by the fields, 
     1671including the current field (e.g., the field XXX if you're in clean_XXX()). 
    11281672>>> class UserRegistration(Form): 
    11291673...    username = CharField(max_length=10) 
     
    11351679...        return self.clean_data['password2'] 
    11361680>>> f = UserRegistration() 
    1137 >>> f.errors() 
     1681>>> f.errors 
     1682{} 
     1683>>> f = UserRegistration({}) 
     1684>>> f.errors 
    11381685{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']} 
    11391686>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}) 
    1140 >>> f.errors() 
     1687>>> f.errors 
    11411688{'password2': [u'Please make sure your passwords match.']} 
    11421689>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}) 
    1143 >>> f.errors() 
     1690>>> f.errors 
    11441691{} 
    1145 >>> f.clean() 
     1692>>> f.clean_data 
    11461693{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'} 
    11471694 
     
    11491696Form's clean() method. If you do this, any ValidationError raised by that 
    11501697method will not be associated with a particular field; it will have a 
    1151 special-case association with the field named '__all__'. Note that 
    1152 Form.clean() still needs to return a dictionary of all clean data: 
     1698special-case association with the field named '__all__'. 
     1699Note that in Form.clean(), you have access to self.clean_data, a dictionary of 
     1700all the fields/values that have *not* raised a ValidationError. Also note 
     1701Form.clean() is required to return a dictionary of all clean data. 
    11531702>>> class UserRegistration(Form): 
    11541703...    username = CharField(max_length=10) 
     
    11601709...        return self.clean_data 
    11611710>>> f = UserRegistration() 
     1711>>> f.errors 
     1712{} 
     1713>>> f = UserRegistration({}) 
    11621714>>> print f.as_table() 
     1715<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
    11631716<tr><td>Username:</td><td><input type="text" name="username" /></td></tr> 
     1717<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
    11641718<tr><td>Password1:</td><td><input type="password" name="password1" /></td></tr> 
     1719<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
    11651720<tr><td>Password2:</td><td><input type="password" name="password2" /></td></tr> 
    1166 >>> f.errors() 
     1721>>> f.errors 
    11671722{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']} 
    11681723>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}) 
    1169 >>> f.errors() 
     1724>>> f.errors 
    11701725{'__all__': [u'Please make sure your passwords match.']} 
    11711726>>> print f.as_table() 
     1727<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> 
    11721728<tr><td>Username:</td><td><input type="text" name="username" value="adrian" /></td></tr> 
    11731729<tr><td>Password1:</td><td><input type="password" name="password1" value="foo" /></td></tr> 
    11741730<tr><td>Password2:</td><td><input type="password" name="password2" value="bar" /></td></tr> 
    1175 >>> print f.as_table_with_errors() 
    1176 <tr><td colspan="2"><ul><li>Please make sure your passwords match.</li></ul></td></tr> 
    1177 <tr><td>Username:</td><td><input type="text" name="username" value="adrian" /></td></tr> 
    1178 <tr><td>Password1:</td><td><input type="password" name="password1" value="foo" /></td></tr> 
    1179 <tr><td>Password2:</td><td><input type="password" name="password2" value="bar" /></td></tr> 
    1180 >>> print f.as_ul_with_errors() 
    1181 <li><ul><li>Please make sure your passwords match.</li></ul></li> 
     1731>>> print f.as_ul() 
     1732<li><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></li> 
    11821733<li>Username: <input type="text" name="username" value="adrian" /></li> 
    11831734<li>Password1: <input type="password" name="password1" value="foo" /></li> 
    11841735<li>Password2: <input type="password" name="password2" value="bar" /></li> 
    11851736>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}) 
    1186 >>> f.errors() 
     1737>>> f.errors 
    11871738{} 
    1188 >>> f.clean() 
     1739>>> f.clean_data 
    11891740{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'} 
    11901741 
     
    12031754<tr><td>Last name:</td><td><input type="text" name="last_name" /></td></tr> 
    12041755<tr><td>Birthday:</td><td><input type="text" name="birthday" /></td></tr> 
     1756 
     1757HiddenInput widgets are displayed differently in the as_table() and as_ul() 
     1758output of a Form -- their verbose names are not displayed, and a separate 
     1759<tr>/<li> is not displayed. 
     1760>>> class Person(Form): 
     1761...     first_name = CharField() 
     1762...     last_name = CharField() 
     1763...     hidden_text = CharField(widget=HiddenInput) 
     1764...     birthday = DateField() 
     1765>>> p = Person() 
     1766>>> print p 
     1767<tr><td>First name:</td><td><input type="text" name="first_name" /></td></tr> 
     1768<tr><td>Last name:</td><td><input type="text" name="last_name" /></td></tr> 
     1769<input type="hidden" name="hidden_text" /> 
     1770<tr><td>Birthday:</td><td><input type="text" name="birthday" /></td></tr> 
     1771>>> print p.as_ul() 
     1772<li>First name: <input type="text" name="first_name" /></li> 
     1773<li>Last name: <input type="text" name="last_name" /></li> 
     1774<input type="hidden" name="hidden_text" /> 
     1775<li>Birthday: <input type="text" name="birthday" /></li> 
     1776 
     1777With auto_id set, a HiddenInput still gets an ID, but it doesn't get a label. 
     1778>>> p = Person(auto_id='id_%s') 
     1779>>> print p 
     1780<tr><td><label for="id_first_name">First name:</label></td><td><input type="text" name="first_name" id="id_first_name" /></td></tr> 
     1781<tr><td><label for="id_last_name">Last name:</label></td><td><input type="text" name="last_name" id="id_last_name" /></td></tr> 
     1782<input type="hidden" name="hidden_text" id="id_hidden_text" /> 
     1783<tr><td><label for="id_birthday">Birthday:</label></td><td><input type="text" name="birthday" id="id_birthday" /></td></tr> 
     1784>>> print p.as_ul() 
     1785<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li> 
     1786<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li> 
     1787<input type="hidden" name="hidden_text" id="id_hidden_text" /> 
     1788<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li> 
     1789 
     1790If a field with a HiddenInput has errors, the as_table() and as_ul() output 
     1791will include the error message(s) with the text "(Hidden field [fieldname]) " 
     1792prepended. 
     1793>>> p = Person({'first_name': 'John', 'last_name': 'Lennon', 'birthday': '1940-10-9'}) 
     1794>>> print p 
     1795<tr><td>First name:</td><td><input type="text" name="first_name" value="John" /></td></tr> 
     1796<tr><td>Last name:</td><td><input type="text" name="last_name" value="Lennon" /></td></tr> 
     1797<tr><td colspan="2"><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></td></tr> 
     1798<input type="hidden" name="hidden_text" /> 
     1799<tr><td>Birthday:</td><td><input type="text" name="birthday" value="1940-10-9" /></td></tr> 
     1800>>> print p.as_ul() 
     1801<li>First name: <input type="text" name="first_name" value="John" /></li> 
     1802<li>Last name: <input type="text" name="last_name" value="Lennon" /></li> 
     1803<li><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></li> 
     1804<input type="hidden" name="hidden_text" /> 
     1805<li>Birthday: <input type="text" name="birthday" value="1940-10-9" /></li> 
    12051806 
    12061807A Form's fields are displayed in the same order in which they were defined. 
     
    12361837<tr><td>Field13:</td><td><input type="text" name="field13" /></td></tr> 
    12371838<tr><td>Field14:</td><td><input type="text" name="field14" /></td></tr> 
     1839 
     1840# Basic form processing in a view ############################################# 
     1841 
     1842>>> from django.template import Template, Context 
     1843>>> class UserRegistration(Form): 
     1844...    username = CharField(max_length=10) 
     1845...    password1 = CharField(widget=PasswordInput) 
     1846...    password2 = CharField(widget=PasswordInput) 
     1847...    def clean(self): 
     1848...        if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: 
     1849...            raise ValidationError(u'Please make sure your passwords match.') 
     1850...        return self.clean_data 
     1851>>> def my_function(method, post_data): 
     1852...     if method == 'POST': 
     1853...         form = UserRegistration(post_data) 
     1854...     else: 
     1855...         form = UserRegistration() 
     1856...     if form.is_valid(): 
     1857...         return 'VALID: %r' % form.clean_data 
     1858...     t = Template('<form action="" method="post">\n<table>\n{{ form }}\n</table>\n<input type="submit" />\n</form>') 
     1859...     return t.render(Context({'form': form})) 
     1860 
     1861Case 1: GET (an empty form, with no errors). 
     1862>>> print my_function('GET', {}) 
     1863<form action="" method="post"> 
     1864<table> 
     1865<tr><td>Username:</td><td><input type="text" name="username" /></td></tr> 
     1866<tr><td>Password1:</td><td><input type="password" name="password1" /></td></tr> 
     1867<tr><td>Password2:</td><td><input type="password" name="password2" /></td></tr> 
     1868</table> 
     1869<input type="submit" /> 
     1870</form> 
     1871 
     1872Case 2: POST with erroneous data (a redisplayed form, with errors). 
     1873>>> print my_function('POST', {'username': 'this-is-a-long-username', 'password1': 'foo', 'password2': 'bar'}) 
     1874<form action="" method="post"> 
     1875<table> 
     1876<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> 
     1877<tr><td colspan="2"><ul class="errorlist"><li>Ensure this value has at most 10 characters.</li></ul></td></tr> 
     1878<tr><td>Username:</td><td><input type="text" name="username" value="this-is-a-long-username" /></td></tr> 
     1879<tr><td>Password1:</td><td><input type="password" name="password1" value="foo" /></td></tr> 
     1880<tr><td>Password2:</td><td><input type="password" name="password2" value="bar" /></td></tr> 
     1881</table> 
     1882<input type="submit" /> 
     1883</form> 
     1884 
     1885Case 3: POST with valid data (the success message). 
     1886>>> print my_function('POST', {'username': 'adrian', 'password1': 'secret', 'password2': 'secret'}) 
     1887VALID: {'username': u'adrian', 'password1': u'secret', 'password2': u'secret'} 
     1888 
     1889# Some ideas for using templates with forms ################################### 
     1890 
     1891>>> class UserRegistration(Form): 
     1892...    username = CharField(max_length=10) 
     1893...    password1 = CharField(widget=PasswordInput) 
     1894...    password2 = CharField(widget=PasswordInput) 
     1895...    def clean(self): 
     1896...        if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: 
     1897...            raise ValidationError(u'Please make sure your passwords match.') 
     1898...        return self.clean_data 
     1899 
     1900You have full flexibility in displaying form fields in a template. Just pass a 
     1901Form instance to the template, and use "dot" access to refer to individual 
     1902fields. Note, however, that this flexibility comes with the responsibility of 
     1903displaying all the errors, including any that might not be associated with a 
     1904particular field. 
     1905>>> t = Template('''<form action=""> 
     1906... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> 
     1907... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> 
     1908... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> 
     1909... <input type="submit" /> 
     1910... </form>''') 
     1911>>> print t.render(Context({'form': UserRegistration()})) 
     1912<form action=""> 
     1913<p><label>Your username: <input type="text" name="username" /></label></p> 
     1914<p><label>Password: <input type="password" name="password1" /></label></p> 
     1915<p><label>Password (again): <input type="password" name="password2" /></label></p> 
     1916<input type="submit" /> 
     1917</form> 
     1918>>> print t.render(Context({'form': UserRegistration({'username': 'django'})})) 
     1919<form action=""> 
     1920<p><label>Your username: <input type="text" name="username" value="django" /></label></p> 
     1921<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password: <input type="password" name="password1" /></label></p> 
     1922<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password (again): <input type="password" name="password2" /></label></p> 
     1923<input type="submit" /> 
     1924</form> 
     1925 
     1926Use form.[field].verbose_name to output a field's "verbose name" -- its field 
     1927name with underscores converted to spaces, and the initial letter capitalized. 
     1928>>> t = Template('''<form action=""> 
     1929... <p><label>{{ form.username.verbose_name }}: {{ form.username }}</label></p> 
     1930... <p><label>{{ form.password1.verbose_name }}: {{ form.password1 }}</label></p> 
     1931... <p><label>{{ form.password2.verbose_name }}: {{ form.password2 }}</label></p> 
     1932... <input type="submit" /> 
     1933... </form>''') 
     1934>>> print t.render(Context({'form': UserRegistration()})) 
     1935<form action=""> 
     1936<p><label>Username: <input type="text" name="username" /></label></p> 
     1937<p><label>Password1: <input type="password" name="password1" /></label></p> 
     1938<p><label>Password2: <input type="password" name="password2" /></label></p> 
     1939<input type="submit" /> 
     1940</form> 
     1941 
     1942User form.[field].label_tag to output a field's verbose_name with a <label> 
     1943tag wrapped around it, but *only* if the given field has an "id" attribute. 
     1944Recall from above that passing the "auto_id" argument to a Form gives each 
     1945field an "id" attribute. 
     1946>>> t = Template('''<form action=""> 
     1947... <p>{{ form.username.label_tag }}: {{ form.username }}</p> 
     1948... <p>{{ form.password1.label_tag }}: {{ form.password1 }}</p> 
     1949... <p>{{ form.password2.label_tag }}: {{ form.password2 }}</p> 
     1950... <input type="submit" /> 
     1951... </form>''') 
     1952>>> print t.render(Context({'form': UserRegistration()})) 
     1953<form action=""> 
     1954<p>Username: <input type="text" name="username" /></p> 
     1955<p>Password1: <input type="password" name="password1" /></p> 
     1956<p>Password2: <input type="password" name="password2" /></p> 
     1957<input type="submit" /> 
     1958</form> 
     1959>>> print t.render(Context({'form': UserRegistration(auto_id='id_%s')})) 
     1960<form action=""> 
     1961<p><label for="id_username">Username</label>: <input type="text" name="username" id="id_username" /></p> 
     1962<p><label for="id_password1">Password1</label>: <input type="password" name="password1" id="id_password1" /></p> 
     1963<p><label for="id_password2">Password2</label>: <input type="password" name="password2" id="id_password2" /></p> 
     1964<input type="submit" /> 
     1965</form> 
     1966 
     1967To display the errors that aren't associated with a particular field -- e.g., 
     1968the errors caused by Form.clean() -- use {{ form.non_field_errors }} in the 
     1969template. If used on its own, it is displayed as a <ul> (or an empty string, if 
     1970the list of errors is empty). You can also use it in {% if %} statements. 
     1971>>> t = Template('''<form action=""> 
     1972... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> 
     1973... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> 
     1974... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> 
     1975... <input type="submit" /> 
     1976... </form>''') 
     1977>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'})})) 
     1978<form action=""> 
     1979<p><label>Your username: <input type="text" name="username" value="django" /></label></p> 
     1980<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> 
     1981<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> 
     1982<input type="submit" /> 
     1983</form> 
     1984>>> t = Template('''<form action=""> 
     1985... {{ form.non_field_errors }} 
     1986... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> 
     1987... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> 
     1988... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> 
     1989... <input type="submit" /> 
     1990... </form>''') 
     1991>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'})})) 
     1992<form action=""> 
     1993<ul class="errorlist"><li>Please make sure your passwords match.</li></ul> 
     1994<p><label>Your username: <input type="text" name="username" value="django" /></label></p> 
     1995<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> 
     1996<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> 
     1997<input type="submit" /> 
     1998</form> 
    12381999""" 
    12392000