diff --git a/django/newforms/forms.py b/django/newforms/forms.py index 0b90b09e2c..1032d02e35 100644 --- a/django/newforms/forms.py +++ b/django/newforms/forms.py @@ -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) diff --git a/docs/newforms.txt b/docs/newforms.txt index 063f686ed5..ff222516b3 100644 --- a/docs/newforms.txt +++ b/docs/newforms.txt @@ -571,6 +571,46 @@ is a list-like object that is displayed as an HTML ``