Django

Code

Show
Ignore:
Timestamp:
06/17/07 17:18:54 (2 years ago)
Author:
clong
Message:

per-object-permissions: Merged to trunk [5486] NOTE: Not fully tested, will be working on this over the next few weeks.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/per-object-permissions/tests/regressiontests/cache/tests.py

    r3669 r5488  
    4747        self.assertEqual(cache.has_key("goodbye"), False) 
    4848 
     49    def test_in(self):  
     50        cache.set("hello", "goodbye")  
     51        self.assertEqual("hello" in cache, True)  
     52        self.assertEqual("goodbye" in cache, False)  
     53 
    4954    def test_data_types(self): 
    5055        # test data types 
  • django/branches/per-object-permissions/tests/regressiontests/dateformat/tests.py

    r3940 r5488  
    1818>>> format(my_birthday, 'M') 
    1919'Jul' 
     20>>> format(my_birthday, 'b') 
     21'jul' 
    2022>>> format(my_birthday, 'n') 
    2123'7' 
  • django/branches/per-object-permissions/tests/regressiontests/defaultfilters/tests.py

    r3810 r5488  
     1# -*- coding: utf-8 -*- 
     2 
    13r""" 
    24>>> floatformat(7.7) 
     
    1214>>> floatformat(0.0) 
    1315'0' 
     16>>> floatformat(7.7,3) 
     17'7.700' 
     18>>> floatformat(6.000000,3) 
     19'6.000' 
     20>>> floatformat(13.1031,-3) 
     21'13.103' 
     22>>> floatformat(11.1197, -2) 
     23'11.12' 
     24>>> floatformat(11.0000, -2) 
     25'11' 
     26>>> floatformat(11.000001, -2) 
     27'11.00' 
     28>>> floatformat(8.2798, 3) 
     29'8.280' 
     30>>> floatformat('foo') 
     31'' 
     32>>> floatformat(13.1031, 'bar') 
     33'13.1031' 
     34>>> floatformat('foo', 'bar') 
     35'' 
    1436 
    1537>>> addslashes('"double quotes" and \'single quotes\'') 
     
    6890'A sentence with a few words in it' 
    6991 
     92>>> truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 0) 
     93'' 
     94 
     95>>> truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 2) 
     96'<p>one <a href="#">two ...</a></p>' 
     97 
     98>>> truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 4) 
     99'<p>one <a href="#">two - three <br>four ...</a></p>' 
     100 
     101>>> truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 5) 
     102'<p>one <a href="#">two - three <br>four</a> five</p>' 
     103 
     104>>> truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 100) 
     105'<p>one <a href="#">two - three <br>four</a> five</p>' 
    70106 
    71107>>> upper('Mixed case input') 
     
    78114>>> urlencode('jack & jill') 
    79115'jack%20%26%20jill' 
     116>>> urlencode(1) 
     117'1' 
    80118 
    81119 
     
    98136"this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid" 
    99137 
     138>>> wordwrap('this is a short paragraph of text.\n  But this line should be indented',14) 
     139'this is a\nshort\nparagraph of\ntext.\n  But this\nline should be\nindented' 
     140 
     141>>> wordwrap('this is a short paragraph of text.\n  But this line should be indented',15) 
     142'this is a short\nparagraph of\ntext.\n  But this line\nshould be\nindented' 
     143 
    100144>>> ljust('test', 10) 
    101145'test      ' 
     
    124168>>> escape('<some html & special characters > here') 
    125169'&lt;some html &amp; special characters &gt; here' 
     170 
     171>>> escape(u'<some html & special characters > here ĐÅ€£') 
     172u'&lt;some html &amp; special characters &gt; here \xc4\x90\xc3\x85\xe2\x82\xac\xc2\xa3' 
    126173 
    127174>>> linebreaks('line 1') 
     
    353400'0800 3569377' 
    354401 
    355  
     402# Filters shouldn't break if passed non-strings 
     403>>> addslashes(123) 
     404'123' 
     405>>> linenumbers(123) 
     406'1. 123' 
     407>>> lower(123) 
     408'123' 
     409>>> make_list(123) 
     410['1', '2', '3'] 
     411>>> slugify(123) 
     412'123' 
     413>>> title(123) 
     414'123' 
     415>>> truncatewords(123, 2) 
     416'123' 
     417>>> upper(123) 
     418'123' 
     419>>> urlencode(123) 
     420'123' 
     421>>> urlize(123) 
     422'123' 
     423>>> urlizetrunc(123, 1) 
     424'123' 
     425>>> wordcount(123) 
     426
     427>>> wordwrap(123, 2) 
     428'123' 
     429>>> ljust('123', 4) 
     430'123 ' 
     431>>> rjust('123', 4) 
     432' 123' 
     433>>> center('123', 5) 
     434' 123 ' 
     435>>> center('123', 6) 
     436' 123  ' 
     437>>> cut(123, '2') 
     438'13' 
     439>>> escape(123) 
     440'123' 
     441>>> linebreaks(123) 
     442'<p>123</p>' 
     443>>> linebreaksbr(123) 
     444'123' 
     445>>> removetags(123, 'a') 
     446'123' 
     447>>> striptags(123) 
     448'123' 
    356449 
    357450""" 
  • django/branches/per-object-permissions/tests/regressiontests/forms/tests.py

    r4242 r5488  
    11# -*- coding: utf-8 -*- 
    2 r""" 
     2from localflavor import localflavor_tests 
     3from regressions import regression_tests 
     4 
     5form_tests = r""" 
    36>>> from django.newforms import * 
    47>>> import datetime 
     8>>> import time 
    59>>> import re 
     10>>> try: 
     11...     from decimal import Decimal 
     12... except ImportError: 
     13...     from django.utils._decimal import Decimal 
    614 
    715########### 
     
    7381u'<input type="password" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' 
    7482 
     83The render_value argument lets you specify whether the widget should render 
     84its value. You may want to do this for security reasons. 
     85>>> w = PasswordInput(render_value=True) 
     86>>> w.render('email', 'secret') 
     87u'<input type="password" name="email" value="secret" />' 
     88>>> w = PasswordInput(render_value=False) 
     89>>> w.render('email', '') 
     90u'<input type="password" name="email" />' 
     91>>> w.render('email', None) 
     92u'<input type="password" name="email" />' 
     93>>> w.render('email', 'secret') 
     94u'<input type="password" name="email" />' 
     95>>> w = PasswordInput(attrs={'class': 'fun'}, render_value=False) 
     96>>> w.render('email', 'secret') 
     97u'<input type="password" class="fun" name="email" />' 
     98 
    7599# HiddenInput Widget ############################################################ 
    76100 
     
    107131u'<input type="hidden" class="special" name="email" />' 
    108132 
     133# MultipleHiddenInput Widget ################################################## 
     134 
     135>>> w = MultipleHiddenInput() 
     136>>> w.render('email', []) 
     137u'' 
     138>>> w.render('email', None) 
     139u'' 
     140>>> w.render('email', ['test@example.com']) 
     141u'<input type="hidden" name="email" value="test@example.com" />' 
     142>>> w.render('email', ['some "quoted" & ampersanded value']) 
     143u'<input type="hidden" name="email" value="some &quot;quoted&quot; &amp; ampersanded value" />' 
     144>>> w.render('email', ['test@example.com', 'foo@example.com']) 
     145u'<input type="hidden" name="email" value="test@example.com" />\n<input type="hidden" name="email" value="foo@example.com" />' 
     146>>> w.render('email', ['test@example.com'], attrs={'class': 'fun'}) 
     147u'<input type="hidden" name="email" value="test@example.com" class="fun" />' 
     148>>> w.render('email', ['test@example.com', 'foo@example.com'], attrs={'class': 'fun'}) 
     149u'<input type="hidden" name="email" value="test@example.com" class="fun" />\n<input type="hidden" name="email" value="foo@example.com" class="fun" />' 
     150 
     151You can also pass 'attrs' to the constructor: 
     152>>> w = MultipleHiddenInput(attrs={'class': 'fun'}) 
     153>>> w.render('email', []) 
     154u'' 
     155>>> w.render('email', ['foo@example.com']) 
     156u'<input type="hidden" class="fun" value="foo@example.com" name="email" />' 
     157>>> w.render('email', ['foo@example.com', 'test@example.com']) 
     158u'<input type="hidden" class="fun" value="foo@example.com" name="email" />\n<input type="hidden" class="fun" value="test@example.com" name="email" />' 
     159 
     160'attrs' passed to render() get precedence over those passed to the constructor: 
     161>>> w = MultipleHiddenInput(attrs={'class': 'pretty'}) 
     162>>> w.render('email', ['foo@example.com'], attrs={'class': 'special'}) 
     163u'<input type="hidden" class="special" value="foo@example.com" name="email" />' 
     164 
     165>>> w.render('email', ['ŠĐĆŽćžšđ'], attrs={'class': 'fun'}) 
     166u'<input type="hidden" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' 
     167 
     168'attrs' passed to render() get precedence over those passed to the constructor: 
     169>>> w = MultipleHiddenInput(attrs={'class': 'pretty'}) 
     170>>> w.render('email', ['foo@example.com'], attrs={'class': 'special'}) 
     171u'<input type="hidden" class="special" value="foo@example.com" name="email" />' 
     172 
    109173# FileInput Widget ############################################################ 
    110174 
     
    135199>>> w = Textarea() 
    136200>>> w.render('msg', '') 
    137 u'<textarea name="msg"></textarea>' 
     201u'<textarea rows="10" cols="40" name="msg"></textarea>' 
    138202>>> w.render('msg', None) 
    139 u'<textarea name="msg"></textarea>' 
     203u'<textarea rows="10" cols="40" name="msg"></textarea>' 
    140204>>> w.render('msg', 'value') 
    141 u'<textarea name="msg">value</textarea>' 
     205u'<textarea rows="10" cols="40" name="msg">value</textarea>' 
    142206>>> w.render('msg', 'some "quoted" & ampersanded value') 
    143 u'<textarea name="msg">some &quot;quoted&quot; &amp; ampersanded value</textarea>' 
    144 >>> w.render('msg', 'value', attrs={'class': 'pretty'}) 
    145 u'<textarea name="msg" class="pretty">value</textarea>' 
     207u'<textarea rows="10" cols="40" name="msg">some &quot;quoted&quot; &amp; ampersanded value</textarea>' 
     208>>> w.render('msg', 'value', attrs={'class': 'pretty', 'rows': 20}) 
     209u'<textarea class="pretty" rows="20" cols="40" name="msg">value</textarea>' 
    146210 
    147211You can also pass 'attrs' to the constructor: 
    148212>>> w = Textarea(attrs={'class': 'pretty'}) 
    149213>>> w.render('msg', '') 
    150 u'<textarea class="pretty" name="msg"></textarea>' 
     214u'<textarea rows="10" cols="40" name="msg" class="pretty"></textarea>' 
    151215>>> w.render('msg', 'example') 
    152 u'<textarea class="pretty" name="msg">example</textarea>' 
     216u'<textarea rows="10" cols="40" name="msg" class="pretty">example</textarea>' 
    153217 
    154218'attrs' passed to render() get precedence over those passed to the constructor: 
    155219>>> w = Textarea(attrs={'class': 'pretty'}) 
    156220>>> w.render('msg', '', attrs={'class': 'special'}) 
    157 u'<textarea class="special" name="msg"></textarea>' 
     221u'<textarea rows="10" cols="40" name="msg" class="special"></textarea>' 
    158222 
    159223>>> w.render('msg', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) 
    160 u'<textarea class="fun" name="msg">\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</textarea>' 
     224u'<textarea rows="10" cols="40" name="msg" class="fun">\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</textarea>' 
    161225 
    162226# CheckboxInput Widget ######################################################## 
     
    263327 
    264328The 'choices' argument can be any iterable: 
     329>>> from itertools import chain 
    265330>>> def get_choices(): 
    266331...     for i in range(5): 
     
    274339<option value="4">4</option> 
    275340</select> 
     341>>> things = ({'id': 1, 'name': 'And Boom'}, {'id': 2, 'name': 'One More Thing!'}) 
     342>>> class SomeForm(Form): 
     343...     somechoice = ChoiceField(choices=chain((('', '-'*9),), [(thing['id'], thing['name']) for thing in things])) 
     344>>> f = SomeForm() 
     345>>> f.as_table() 
     346u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>' 
     347>>> f.as_table() 
     348u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>' 
     349>>> f = SomeForm({'somechoice': 2}) 
     350>>> f.as_table() 
     351u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="">---------</option>\n<option value="1">And Boom</option>\n<option value="2" selected="selected">One More Thing!</option>\n</select></td></tr>' 
    276352 
    277353You can also pass 'choices' to the constructor: 
     
    296372>>> w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) 
    297373u'<select name="email">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>' 
     374 
     375If choices is passed to the constructor and is a generator, it can be iterated 
     376over multiple times without getting consumed: 
     377>>> w = Select(choices=get_choices()) 
     378>>> print w.render('num', 2) 
     379<select name="num"> 
     380<option value="0">0</option> 
     381<option value="1">1</option> 
     382<option value="2" selected="selected">2</option> 
     383<option value="3">3</option> 
     384<option value="4">4</option> 
     385</select> 
     386>>> print w.render('num', 3) 
     387<select name="num"> 
     388<option value="0">0</option> 
     389<option value="1">1</option> 
     390<option value="2">2</option> 
     391<option value="3" selected="selected">3</option> 
     392<option value="4">4</option> 
     393</select> 
     394 
     395# NullBooleanSelect Widget #################################################### 
     396 
     397>>> w = NullBooleanSelect() 
     398>>> print w.render('is_cool', True) 
     399<select name="is_cool"> 
     400<option value="1">Unknown</option> 
     401<option value="2" selected="selected">Yes</option> 
     402<option value="3">No</option> 
     403</select> 
     404>>> print w.render('is_cool', False) 
     405<select name="is_cool"> 
     406<option value="1">Unknown</option> 
     407<option value="2">Yes</option> 
     408<option value="3" selected="selected">No</option> 
     409</select> 
     410>>> print w.render('is_cool', None) 
     411<select name="is_cool"> 
     412<option value="1" selected="selected">Unknown</option> 
     413<option value="2">Yes</option> 
     414<option value="3">No</option> 
     415</select> 
     416>>> print w.render('is_cool', '2') 
     417<select name="is_cool"> 
     418<option value="1">Unknown</option> 
     419<option value="2" selected="selected">Yes</option> 
     420<option value="3">No</option> 
     421</select> 
     422>>> print w.render('is_cool', '3') 
     423<select name="is_cool"> 
     424<option value="1">Unknown</option> 
     425<option value="2">Yes</option> 
     426<option value="3" selected="selected">No</option> 
     427</select> 
    298428 
    299429# SelectMultiple Widget ####################################################### 
     
    528658False 
    529659>>> r[1].name, r[1].value, r[1].choice_value, r[1].choice_label 
    530 ('beatle', u'J', 'P', 'Paul') 
     660('beatle', u'J', u'P', u'Paul') 
    531661>>> r[10] 
    532662Traceback (most recent call last): 
    533663... 
    534664IndexError: list index out of range 
     665 
     666# Unicode choices are correctly rendered as HTML 
     667>>> w = RadioSelect() 
     668>>> unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])) 
     669u'<ul>\n<li><label><input checked="checked" type="radio" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="radio" name="email" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>' 
     670 
     671# Attributes provided at instantiation are passed to the constituent inputs 
     672>>> w = RadioSelect(attrs={'id':'foo'}) 
     673>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) 
     674<ul> 
     675<li><label><input checked="checked" type="radio" id="foo_0" value="J" name="beatle" /> John</label></li> 
     676<li><label><input type="radio" id="foo_1" value="P" name="beatle" /> Paul</label></li> 
     677<li><label><input type="radio" id="foo_2" value="G" name="beatle" /> George</label></li> 
     678<li><label><input type="radio" id="foo_3" value="R" name="beatle" /> Ringo</label></li> 
     679</ul> 
     680 
     681# Attributes provided at render-time are passed to the constituent inputs 
     682>>> w = RadioSelect() 
     683>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')), attrs={'id':'bar'}) 
     684<ul> 
     685<li><label><input checked="checked" type="radio" id="bar_0" value="J" name="beatle" /> John</label></li> 
     686<li><label><input type="radio" id="bar_1" value="P" name="beatle" /> Paul</label></li> 
     687<li><label><input type="radio" id="bar_2" value="G" name="beatle" /> George</label></li> 
     688<li><label><input type="radio" id="bar_3" value="R" name="beatle" /> Ringo</label></li> 
     689</ul> 
    535690 
    536691# CheckboxSelectMultiple Widget ############################################### 
     
    641796u'<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>' 
    642797 
     798# MultiWidget ################################################################# 
     799 
     800>>> class MyMultiWidget(MultiWidget): 
     801...     def decompress(self, value): 
     802...         if value: 
     803...             return value.split('__') 
     804...         return ['', ''] 
     805...     def format_output(self, rendered_widgets): 
     806...         return u'<br />'.join(rendered_widgets) 
     807>>> w = MyMultiWidget(widgets=(TextInput(attrs={'class': 'big'}), TextInput(attrs={'class': 'small'}))) 
     808>>> w.render('name', ['john', 'lennon']) 
     809u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />' 
     810>>> w.render('name', 'john__lennon') 
     811u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />' 
     812>>> w.render('name', 'john__lennon', attrs={'id':'foo'}) 
     813u'<input id="foo_0" type="text" class="big" value="john" name="name_0" /><br /><input id="foo_1" type="text" class="small" value="lennon" name="name_1" />' 
     814>>> w = MyMultiWidget(widgets=(TextInput(attrs={'class': 'big'}), TextInput(attrs={'class': 'small'})), attrs={'id': 'bar'}) 
     815>>> w.render('name', ['john', 'lennon']) 
     816u'<input id="bar_0" type="text" class="big" value="john" name="name_0" /><br /><input id="bar_1" type="text" class="small" value="lennon" name="name_1" />' 
     817 
     818# SplitDateTimeWidget ######################################################### 
     819 
     820>>> w = SplitDateTimeWidget() 
     821>>> w.render('date', '') 
     822u'<input type="text" name="date_0" /><input type="text" name="date_1" />' 
     823>>> w.render('date', None) 
     824u'<input type="text" name="date_0" /><input type="text" name="date_1" />' 
     825>>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30)) 
     826u'<input type="text" name="date_0" value="2006-01-10" /><input type="text" name="date_1" value="07:30:00" />' 
     827>>> w.render('date', [datetime.date(2006, 1, 10), datetime.time(7, 30)]) 
     828u'<input type="text" name="date_0" value="2006-01-10" /><input type="text" name="date_1" value="07:30:00" />' 
     829 
     830You can also pass 'attrs' to the constructor. In this case, the attrs will be 
     831included on both widgets. 
     832>>> w = SplitDateTimeWidget(attrs={'class': 'pretty'}) 
     833>>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30)) 
     834u'<input type="text" class="pretty" value="2006-01-10" name="date_0" /><input type="text" class="pretty" value="07:30:00" name="date_1" />' 
     835 
    643836########## 
    644837# Fields # 
     
    659852             a form. By default, Django will use a "pretty" version of the form 
    660853             field name, if the Field is part of a Form. 
     854    initial -- A value to use in this Field's initial display. This value is 
     855               *not* used as a fallback if data isn't given. 
    661856 
    662857Other than that, the Field subclasses have class-specific options for 
     
    765960>>> f = IntegerField(required=False) 
    766961>>> f.clean('') 
    767 u'' 
     962>>> repr(f.clean('')) 
     963'None' 
    768964>>> f.clean(None) 
    769 u'' 
     965>>> repr(f.clean(None)) 
     966'None' 
    770967>>> f.clean('1') 
    7719681 
     
    8531050... 
    8541051ValidationError: [u'Ensure this value is less than or equal to 20.'] 
     1052 
     1053# FloatField ################################################################## 
     1054 
     1055>>> f = FloatField() 
     1056>>> f.clean('') 
     1057Traceback (most recent call last): 
     1058... 
     1059ValidationError: [u'This field is required.'] 
     1060>>> f.clean(None) 
     1061Traceback (most recent call last): 
     1062... 
     1063ValidationError: [u'This field is required.'] 
     1064>>> f.clean('1') 
     10651.0 
     1066>>> isinstance(f.clean('1'), float) 
     1067True 
     1068>>> f.clean('23') 
     106923.0 
     1070>>> f.clean('3.14') 
     10713.1400000000000001 
     1072>>> f.clean('a') 
     1073Traceback (most recent call last): 
     1074... 
     1075ValidationError: [u'Enter a number.'] 
     1076>>> f.clean('1.0 ') 
     10771.0 
     1078>>> f.clean(' 1.0') 
     10791.0 
     1080>>> f.clean(' 1.0 ') 
     10811.0 
     1082>>> f.clean('1.0a') 
     1083Traceback (most recent call last): 
     1084... 
     1085ValidationError: [u'Enter a number.'] 
     1086 
     1087>>> f = FloatField(required=False) 
     1088>>> f.clean('') 
     1089 
     1090>>> f.clean(None) 
     1091 
     1092>>> f.clean('1') 
     10931.0 
     1094 
     1095FloatField accepts min_value and max_value just like IntegerField: 
     1096>>> f = FloatField(max_value=1.5, min_value=0.5) 
     1097 
     1098>>> f.clean('1.6') 
     1099Traceback (most recent call last): 
     1100... 
     1101ValidationError: [u'Ensure this value is less than or equal to 1.5.'] 
     1102>>> f.clean('0.4') 
     1103Traceback (most recent call last): 
     1104... 
     1105ValidationError: [u'Ensure this value is greater than or equal to 0.5.'] 
     1106>>> f.clean('1.5') 
     11071.5 
     1108>>> f.clean('0.5') 
     11090.5 
     1110 
     1111# DecimalField ################################################################ 
     1112 
     1113>>> f = DecimalField(max_digits=4, decimal_places=2) 
     1114>>> f.clean('') 
     1115Traceback (most recent call last): 
     1116... 
     1117ValidationError: [u'This field is required.'] 
     1118>>> f.clean(None) 
     1119Traceback (most recent call last): 
     1120... 
     1121ValidationError: [u'This field is required.'] 
     1122>>> f.clean('1') 
     1123Decimal("1") 
     1124>>> isinstance(f.clean('1'), Decimal) 
     1125True 
     1126>>> f.clean('23') 
     1127Decimal("23") 
     1128>>> f.clean('3.14') 
     1129Decimal("3.14") 
     1130>>> f.clean('a') 
     1131Traceback (most recent call last): 
     1132... 
     1133ValidationError: [u'Enter a number.'] 
     1134>>> f.clean('1.0 ') 
     1135Decimal("1.0") 
     1136>>> f.clean(' 1.0') 
     1137Decimal("1.0") 
     1138>>> f.clean(' 1.0 ') 
     1139Decimal("1.0") 
     1140>>> f.clean('1.0a') 
     1141Traceback (most recent call last): 
     1142... 
     1143ValidationError: [u'Enter a number.'] 
     1144>>> f.clean('123.45') 
     1145Traceback (most recent call last): 
     1146... 
     1147ValidationError: [u'Ensure that there are no more than 4 digits in total.'] 
     1148>>> f.clean('1.234') 
     1149Traceback (most recent call last): 
     1150... 
     1151ValidationError: [u'Ensure that there are no more than 2 decimal places.'] 
     1152>>> f.clean('123.4') 
     1153Traceback (most recent call last): 
     1154... 
     1155ValidationError: [u'Ensure that there are no more than 2 digits before the decimal point.'] 
     1156>>> f = DecimalField(max_digits=4, decimal_places=2, required=False) 
     1157>>> f.clean('') 
     1158 
     1159>>> f.clean(None) 
     1160 
     1161>>> f.clean('1') 
     1162Decimal("1") 
     1163 
     1164DecimalField accepts min_value and max_value just like IntegerField: 
     1165>>> f = DecimalField(max_digits=4, decimal_places=2, max_value=Decimal('1.5'), min_value=Decimal('0.5')) 
     1166 
     1167>>> f.clean('1.6') 
     1168Traceback (most recent call last): 
     1169... 
     1170ValidationError: [u'Ensure this value is less than or equal to 1.5.'] 
     1171>>> f.clean('0.4') 
     1172Traceback (most recent call last): 
     1173... 
     1174ValidationError: [u'Ensure this value is greater than or equal to 0.5.'] 
     1175>>> f.clean('1.5') 
     1176Decimal("1.5") 
     1177>>> f.clean('0.5') 
     1178Decimal("0.5") 
    8551179 
    8561180# DateField ################################################################### 
     
    12841608... 
    12851609ValidationError: [u'This URL appears to be a broken link.'] 
    1286  
    1287 EmailField also access min_length and max_length parameters, for convenience. 
     1610>>> f = URLField(verify_exists=True, required=False) 
     1611>>> f.clean('') 
     1612u'' 
     1613>>> f.clean('http://www.google.com') # This will fail if there's no Internet connection 
     1614u'http://www.google.com' 
     1615 
     1616URLField also access min_length and max_length parameters, for convenience. 
    12881617>>> f = URLField(min_length=15, max_length=20) 
    12891618>>> f.clean('http://f.com') 
     
    13541683Traceback (most recent call last): 
    13551684... 
    1356 ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] 
     1685ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] 
    13571686 
    13581687>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')], required=False) 
     
    13681697Traceback (most recent call last): 
    13691698... 
    1370 ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] 
     1699ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] 
    13711700 
    13721701>>> f = ChoiceField(choices=[('J', 'John'), ('P', 'Paul')]) 
     
    13761705Traceback (most recent call last): 
    13771706... 
    1378 ValidationError: [u'Select a valid choice. John is not one of the available choices.'] 
     1707ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] 
     1708 
     1709# NullBooleanField ############################################################ 
     1710 
     1711>>> f = NullBooleanField() 
     1712>>> f.clean('') 
     1713>>> f.clean(True) 
     1714True 
     1715>>> f.clean(False) 
     1716False 
     1717>>> f.clean(None) 
     1718>>> f.clean('1') 
     1719>>> f.clean('2') 
     1720>>> f.clean('3') 
     1721>>> f.clean('hello') 
    13791722 
    13801723# MultipleChoiceField ######################################################### 
     
    14841827u'' 
    14851828 
     1829# SplitDateTimeField ########################################################## 
     1830 
     1831>>> f = SplitDateTimeField() 
     1832>>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)]) 
     1833datetime.datetime(2006, 1, 10, 7, 30) 
     1834>>> f.clean(None) 
     1835Traceback (most recent call last): 
     1836... 
     1837ValidationError: [u'This field is required.'] 
     1838>>> f.clean('') 
     1839Traceback (most recent call last): 
     1840... 
     1841ValidationError: [u'This field is required.'] 
     1842>>> f.clean('hello') 
     1843Traceback (most recent call last): 
     1844... 
     1845ValidationError: [u'Enter a list of values.'] 
     1846>>> f.clean(['hello', 'there']) 
     1847Traceback (most recent call last): 
     1848... 
     1849ValidationError: [u'Enter a valid date.', u'Enter a valid time.'] 
     1850>>> f.clean(['2006-01-10', 'there']) 
     1851Traceback (most recent call last): 
     1852... 
     1853ValidationError: [u'Enter a valid time.'] 
     1854>>> f.clean(['hello', '07:30']) 
     1855Traceback (most recent call last): 
     1856... 
     1857ValidationError: [u'Enter a valid date.'] 
     1858 
     1859>>> f = SplitDateTimeField(required=False) 
     1860>>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)]) 
     1861datetime.datetime(2006, 1, 10, 7, 30) 
     1862>>> f.clean(None) 
     1863>>> f.clean('') 
     1864>>> f.clean('hello') 
     1865Traceback (most recent call last): 
     1866... 
     1867ValidationError: [u'Enter a list of values.'] 
     1868>>> f.clean(['hello', 'there']) 
     1869Traceback (most recent call last): 
     1870... 
     1871ValidationError: [u'Enter a valid date.', u'Enter a valid time.'] 
     1872>>> f.clean(['2006-01-10', 'there']) 
     1873Traceback (most recent call last): 
     1874... 
     1875ValidationError: [u'Enter a valid time.'] 
     1876>>> f.clean(['hello', '07:30']) 
     1877Traceback (most recent call last): 
     1878... 
     1879ValidationError: [u'Enter a valid date.'] 
     1880 
    14861881######### 
    14871882# Forms # 
     
    15011896Pass a dictionary to a Form's __init__(). 
    15021897>>> p = Person({'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9'}) 
     1898>>> p.is_bound 
     1899True 
    15031900>>> p.errors 
    15041901{} 
     
    15091906>>> p.errors.as_text() 
    15101907u'' 
    1511 >>> p.clean_data 
     1908>>> p.cleaned_data 
    15121909{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} 
    15131910>>> print p['first_name'] 
     
    15391936Empty dictionaries are valid, too. 
    15401937>>> p = Person({}) 
     1938>>> p.is_bound 
     1939True 
    15411940>>> p.errors 
    15421941{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} 
    15431942>>> p.is_valid() 
    15441943False 
     1944>>> p.cleaned_data 
     1945Traceback (most recent call last): 
     1946... 
     1947AttributeError: 'Person' object has no attribute 'cleaned_data' 
    15451948>>> print p 
    15461949<tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr> 
     
    15641967 
    15651968If you don't pass any values to the Form's __init__(), or if you pass None, 
    1566 the Form won't do any validation. Form.errors will be an empty dictionary *but* 
    1567 Form.is_valid() will return False. 
     1969the Form will be considered unbound and won't do any validation. Form.errors 
     1970will be an empty dictionary *but* Form.is_valid() will return False. 
    15681971>>> p = Person() 
     1972>>> p.is_bound 
     1973False 
    15691974>>> p.errors 
    15701975{} 
    15711976>>> p.is_valid() 
    15721977False 
     1978>>> p.cleaned_data 
     1979Traceback (most recent call last): 
     1980... 
     1981AttributeError: 'Person' object has no attribute 'cleaned_data' 
    15731982>>> print p 
    15741983<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> 
     
    16092018* birthday 
    16102019  * This field is required. 
    1611 >>> p.clean_data 
    1612 >>> repr(p.clean_data) 
    1613 'None' 
     2020>>> p.cleaned_data 
     2021Traceback (most recent call last): 
     2022... 
     2023AttributeError: 'Person' object has no attribute 'cleaned_data' 
    16142024>>> p['first_name'].errors 
    16152025[u'This field is required.'] 
     
    16262036>>> print p['birthday'] 
    1