Implemented subclassing Forms in newforms
git-svn-id: http://code.djangoproject.com/svn/django/trunk@4506 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4c4209b144
commit
0518205308
|
@ -31,10 +31,21 @@ class SortedDictFromList(SortedDict):
|
|||
return SortedDictFromList([(k, copy.copy(v)) for k, v in self.items()])
|
||||
|
||||
class DeclarativeFieldsMetaclass(type):
|
||||
"Metaclass that converts Field attributes to a dictionary called 'base_fields'."
|
||||
"""
|
||||
Metaclass that converts Field attributes to a dictionary called
|
||||
'base_fields', taking into account parent class 'base_fields' as well.
|
||||
"""
|
||||
def __new__(cls, name, bases, attrs):
|
||||
fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)]
|
||||
fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
|
||||
|
||||
# If this class is subclassing another Form, add that Form's fields.
|
||||
# Note that we loop over the bases in *reverse*. This is necessary in
|
||||
# order to preserve the correct order of fields.
|
||||
for base in bases[::-1]:
|
||||
if hasattr(base, 'base_fields'):
|
||||
fields = base.base_fields.items() + fields
|
||||
|
||||
attrs['base_fields'] = SortedDictFromList(fields)
|
||||
return type.__new__(cls, name, bases, attrs)
|
||||
|
||||
|
|
|
@ -571,6 +571,46 @@ is a list-like object that is displayed as an HTML ``<ul>`` when printed::
|
|||
>>> str(f['subject'].errors)
|
||||
''
|
||||
|
||||
Subclassing forms
|
||||
-----------------
|
||||
|
||||
If you subclass a custom ``Form`` class, the resulting ``Form`` class will
|
||||
include all fields of the parent class(es), followed by the fields you define
|
||||
in the subclass.
|
||||
|
||||
In this example, ``ContactFormWithPriority`` contains all the fields from
|
||||
``ContactForm``, plus an additional field, ``priority``. The ``ContactForm``
|
||||
fields are ordered first::
|
||||
|
||||
>>> class ContactFormWithPriority(ContactForm):
|
||||
... priority = forms.CharField()
|
||||
>>> f = ContactFormWithPriority(auto_id=False)
|
||||
>>> print f.as_ul()
|
||||
<li>Subject: <input type="text" name="subject" maxlength="100" /></li>
|
||||
<li>Message: <input type="text" name="message" /></li>
|
||||
<li>Sender: <input type="text" name="sender" /></li>
|
||||
<li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
|
||||
<li>Priority: <input type="text" name="priority" /></li>
|
||||
|
||||
It's possible to subclass multiple forms, treating forms as "mix-ins." In this
|
||||
example, ``BeatleForm`` subclasses both ``PersonForm`` and ``InstrumentForm``
|
||||
(in that order), and its field list includes the fields from the parent
|
||||
classes::
|
||||
|
||||
>>> class PersonForm(Form):
|
||||
... first_name = CharField()
|
||||
... last_name = CharField()
|
||||
>>> class InstrumentForm(Form):
|
||||
... instrument = CharField()
|
||||
>>> class BeatleForm(PersonForm, InstrumentForm):
|
||||
... haircut_type = CharField()
|
||||
>>> b = Beatle(auto_id=False)
|
||||
>>> print b.as_ul()
|
||||
<li>First name: <input type="text" name="first_name" /></li>
|
||||
<li>Last name: <input type="text" name="last_name" /></li>
|
||||
<li>Instrument: <input type="text" name="instrument" /></li>
|
||||
<li>Haircut type: <input type="text" name="haircut_type" /></li>
|
||||
|
||||
Fields
|
||||
======
|
||||
|
||||
|
|
|
@ -2682,6 +2682,47 @@ purposes, though.
|
|||
<li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li>
|
||||
<li>Password: <input type="password" name="password" /><input type="hidden" name="next" value="/" /></li>
|
||||
|
||||
# Subclassing forms ###########################################################
|
||||
|
||||
You can subclass a Form to add fields. The resulting form subclass will have
|
||||
all of the fields of the parent Form, plus whichever fields you define in the
|
||||
subclass.
|
||||
>>> class Person(Form):
|
||||
... first_name = CharField()
|
||||
... last_name = CharField()
|
||||
... birthday = DateField()
|
||||
>>> class Musician(Person):
|
||||
... instrument = CharField()
|
||||
>>> p = Person(auto_id=False)
|
||||
>>> print p.as_ul()
|
||||
<li>First name: <input type="text" name="first_name" /></li>
|
||||
<li>Last name: <input type="text" name="last_name" /></li>
|
||||
<li>Birthday: <input type="text" name="birthday" /></li>
|
||||
>>> m = Musician(auto_id=False)
|
||||
>>> print m.as_ul()
|
||||
<li>First name: <input type="text" name="first_name" /></li>
|
||||
<li>Last name: <input type="text" name="last_name" /></li>
|
||||
<li>Birthday: <input type="text" name="birthday" /></li>
|
||||
<li>Instrument: <input type="text" name="instrument" /></li>
|
||||
|
||||
Yes, you can subclass multiple forms. The fields are added in the order in
|
||||
which the parent classes are listed.
|
||||
>>> class Person(Form):
|
||||
... first_name = CharField()
|
||||
... last_name = CharField()
|
||||
... birthday = DateField()
|
||||
>>> class Instrument(Form):
|
||||
... instrument = CharField()
|
||||
>>> class Beatle(Person, Instrument):
|
||||
... haircut_type = CharField()
|
||||
>>> b = Beatle(auto_id=False)
|
||||
>>> print b.as_ul()
|
||||
<li>First name: <input type="text" name="first_name" /></li>
|
||||
<li>Last name: <input type="text" name="last_name" /></li>
|
||||
<li>Birthday: <input type="text" name="birthday" /></li>
|
||||
<li>Instrument: <input type="text" name="instrument" /></li>
|
||||
<li>Haircut type: <input type="text" name="haircut_type" /></li>
|
||||
|
||||
# Forms with prefixes #########################################################
|
||||
|
||||
Sometimes it's necessary to have multiple forms display on the same HTML page,
|
||||
|
|
Loading…
Reference in New Issue