Django

Code

Changeset 4187

Show
Ignore:
Timestamp:
12/08/06 12:54:53 (2 years ago)
Author:
adrian
Message:

newforms: Added Field.widget_attrs() hook, which lets a Field designate HTML attributes to use in its widget. Implemented CharField?.widget_attrs(), which sets the HTML maxlength attribute for <input type='text'> and <input type='password'>. Thanks for the idea, Gary Doades

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/newforms/fields.py

    r4185 r4187  
    55from django.utils.translation import gettext 
    66from util import ValidationError, smart_unicode 
    7 from widgets import TextInput, CheckboxInput, Select, SelectMultiple 
     7from widgets import TextInput, PasswordInput, CheckboxInput, Select, SelectMultiple 
    88import datetime 
    99import re 
     
    3838        if isinstance(widget, type): 
    3939            widget = widget() 
     40 
     41        # Hook into self.widget_attrs() for any Field-specific HTML attributes. 
     42        extra_attrs = self.widget_attrs(widget) 
     43        if extra_attrs: 
     44            widget.attrs.update(extra_attrs) 
     45 
    4046        self.widget = widget 
    4147 
     
    5561        return value 
    5662 
     63    def widget_attrs(self, widget): 
     64        """ 
     65        Given a Widget instance (*not* a Widget class), returns a dictionary of 
     66        any HTML attributes that should be added to the Widget, based on this 
     67        Field. 
     68        """ 
     69        return {} 
     70 
    5771class CharField(Field): 
    5872    def __init__(self, max_length=None, min_length=None, required=True, widget=None): 
    59         Field.__init__(self, required, widget) 
    6073        self.max_length, self.min_length = max_length, min_length 
     74        Field.__init__(self, required, widget) 
    6175 
    6276    def clean(self, value): 
     
    7084            raise ValidationError(gettext(u'Ensure this value has at least %d characters.') % self.min_length) 
    7185        return value 
     86 
     87    def widget_attrs(self, widget): 
     88        if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)): 
     89            return {'maxlength': str(self.max_length)} 
    7290 
    7391class IntegerField(Field): 
  • django/trunk/tests/regressiontests/forms/tests.py

    r4178 r4187  
    17371737>>> print f.as_table() 
    17381738<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
    1739 <tr><td>Username:</td><td><input type="text" name="username" /></td></tr> 
     1739<tr><td>Username:</td><td><input type="text" name="username" maxlength="10" /></td></tr> 
    17401740<tr><td colspan="2"><ul class="errorlist"><li>This field is required.</li></ul></td></tr> 
    17411741<tr><td>Password1:</td><td><input type="password" name="password1" /></td></tr> 
     
    17491749>>> print f.as_table() 
    17501750<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> 
    1751 <tr><td>Username:</td><td><input type="text" name="username" value="adrian" /></td></tr> 
     1751<tr><td>Username:</td><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr> 
    17521752<tr><td>Password1:</td><td><input type="password" name="password1" value="foo" /></td></tr> 
    17531753<tr><td>Password2:</td><td><input type="password" name="password2" value="bar" /></td></tr> 
    17541754>>> print f.as_ul() 
    17551755<li><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></li> 
    1756 <li>Username: <input type="text" name="username" value="adrian" /></li> 
     1756<li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li> 
    17571757<li>Password1: <input type="password" name="password1" value="foo" /></li> 
    17581758<li>Password2: <input type="password" name="password2" value="bar" /></li> 
     
    18821882<tr><td>Field14:</td><td><input type="text" name="field14" /></td></tr> 
    18831883 
     1884Some Field classes have an effect on the HTML attributes of their associated 
     1885Widget. If you set max_length in a CharField and its associated widget is 
     1886either a TextInput or PasswordInput, then the widget's rendered HTML will 
     1887include the "maxlength" attribute. 
     1888>>> class UserRegistration(Form): 
     1889...    username = CharField(max_length=10)                   # uses TextInput by default 
     1890...    password = CharField(max_length=10, widget=PasswordInput) 
     1891...    realname = CharField(max_length=10, widget=TextInput) # redundantly define widget, just to test 
     1892...    address = CharField()                                 # no max_length defined here 
     1893>>> p = UserRegistration() 
     1894>>> print p.as_ul() 
     1895<li>Username: <input type="text" name="username" maxlength="10" /></li> 
     1896<li>Password: <input type="password" name="password" maxlength="10" /></li> 
     1897<li>Realname: <input type="text" name="realname" maxlength="10" /></li> 
     1898<li>Address: <input type="text" name="address" /></li> 
     1899 
     1900If you specify a custom "attrs" that includes the "maxlength" attribute, 
     1901the Field's max_length attribute will override whatever "maxlength" you specify 
     1902in "attrs". 
     1903>>> class UserRegistration(Form): 
     1904...    username = CharField(max_length=10, widget=TextInput(attrs={'maxlength': 20})) 
     1905...    password = CharField(max_length=10, widget=PasswordInput) 
     1906>>> p = UserRegistration() 
     1907>>> print p.as_ul() 
     1908<li>Username: <input type="text" name="username" maxlength="10" /></li> 
     1909<li>Password: <input type="password" name="password" maxlength="10" /></li> 
     1910 
    18841911# Basic form processing in a view ############################################# 
    18851912 
     
    19071934<form action="" method="post"> 
    19081935<table> 
    1909 <tr><td>Username:</td><td><input type="text" name="username" /></td></tr> 
     1936<tr><td>Username:</td><td><input type="text" name="username" maxlength="10" /></td></tr> 
    19101937<tr><td>Password1:</td><td><input type="password" name="password1" /></td></tr> 
    19111938<tr><td>Password2:</td><td><input type="password" name="password2" /></td></tr> 
     
    19201947<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> 
    19211948<tr><td colspan="2"><ul class="errorlist"><li>Ensure this value has at most 10 characters.</li></ul></td></tr> 
    1922 <tr><td>Username:</td><td><input type="text" name="username" value="this-is-a-long-username" /></td></tr> 
     1949<tr><td>Username:</td><td><input type="text" name="username" value="this-is-a-long-username" maxlength="10" /></td></tr> 
    19231950<tr><td>Password1:</td><td><input type="password" name="password1" value="foo" /></td></tr> 
    19241951<tr><td>Password2:</td><td><input type="password" name="password2" value="bar" /></td></tr> 
     
    19551982>>> print t.render(Context({'form': UserRegistration()})) 
    19561983<form action=""> 
    1957 <p><label>Your username: <input type="text" name="username" /></label></p> 
     1984<p><label>Your username: <input type="text" name="username" maxlength="10" /></label></p> 
    19581985<p><label>Password: <input type="password" name="password1" /></label></p> 
    19591986<p><label>Password (again): <input type="password" name="password2" /></label></p> 
     
    19621989>>> print t.render(Context({'form': UserRegistration({'username': 'django'})})) 
    19631990<form action=""> 
    1964 <p><label>Your username: <input type="text" name="username" value="django" /></label></p> 
     1991<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> 
    19651992<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password: <input type="password" name="password1" /></label></p> 
    19661993<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password (again): <input type="password" name="password2" /></label></p> 
     
    19782005>>> print t.render(Context({'form': UserRegistration()})) 
    19792006<form action=""> 
    1980 <p><label>Username: <input type="text" name="username" /></label></p> 
     2007<p><label>Username: <input type="text" name="username" maxlength="10" /></label></p> 
    19812008<p><label>Password1: <input type="password" name="password1" /></label></p> 
    19822009<p><label>Password2: <input type="password" name="password2" /></label></p> 
     
    19962023>>> print t.render(Context({'form': UserRegistration()})) 
    19972024<form action=""> 
    1998 <p>Username: <input type="text" name="username" /></p> 
     2025<p>Username: <input type="text" name="username" maxlength="10" /></p> 
    19992026<p>Password1: <input type="password" name="password1" /></p> 
    20002027<p>Password2: <input type="password" name="password2" /></p> 
     
    20032030>>> print t.render(Context({'form': UserRegistration(auto_id='id_%s')})) 
    20042031<form action=""> 
    2005 <p><label for="id_username">Username</label>: <input type="text" name="username" id="id_username" /></p> 
     2032<p><label for="id_username">Username</label>: <input id="id_username" type="text" name="username" maxlength="10" /></p> 
    20062033<p><label for="id_password1">Password1</label>: <input type="password" name="password1" id="id_password1" /></p> 
    20072034<p><label for="id_password2">Password2</label>: <input type="password" name="password2" id="id_password2" /></p> 
     
    20212048>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'})})) 
    20222049<form action=""> 
    2023 <p><label>Your username: <input type="text" name="username" value="django" /></label></p> 
     2050<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> 
    20242051<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> 
    20252052<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> 
     
    20362063<form action=""> 
    20372064<ul class="errorlist"><li>Please make sure your passwords match.</li></ul> 
    2038 <p><label>Your username: <input type="text" name="username" value="django" /></label></p> 
     2065<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> 
    20392066<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> 
    20402067<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p>