diff options
| author | Joseph Kocherhans <joseph@jkocherhans.com> | 2008-02-15 17:05:48 +0000 |
|---|---|---|
| committer | Joseph Kocherhans <joseph@jkocherhans.com> | 2008-02-15 17:05:48 +0000 |
| commit | 7c1242a7a3a62bc63715bc47400827d4cf3c5e05 (patch) | |
| tree | 357594e407b6115ebc4419f2003f3c3282eca344 /django/newforms | |
| parent | daa467d79ec7b40e376294eabc51222a67690181 (diff) | |
newforms-admin: Merged from trunk up to [7120].
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7121 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/newforms')
| -rw-r--r-- | django/newforms/fields.py | 2 | ||||
| -rw-r--r-- | django/newforms/forms.py | 37 | ||||
| -rw-r--r-- | django/newforms/models.py | 73 | ||||
| -rw-r--r-- | django/newforms/widgets.py | 2 |
4 files changed, 58 insertions, 56 deletions
diff --git a/django/newforms/fields.py b/django/newforms/fields.py index 0761b8f2af..bc3e543037 100644 --- a/django/newforms/fields.py +++ b/django/newforms/fields.py @@ -466,6 +466,8 @@ class ImageField(FileField): f = super(ImageField, self).clean(data, initial) if f is None: return None + elif not data and initial: + return initial from PIL import Image from cStringIO import StringIO try: diff --git a/django/newforms/forms.py b/django/newforms/forms.py index 9e1b576710..c8c65975ae 100644 --- a/django/newforms/forms.py +++ b/django/newforms/forms.py @@ -22,24 +22,41 @@ def pretty_name(name): name = name[0].upper() + name[1:] return name.replace('_', ' ') -class DeclarativeFieldsMetaclass(type): +def get_declared_fields(bases, attrs, with_base_fields=True): """ - Metaclass that converts Field attributes to a dictionary called - 'base_fields', taking into account parent class 'base_fields' as well. + Create a list of form field instances from the passed in 'attrs', plus any + similar fields on the base classes (in 'bases'). This is used by both the + Form and ModelForm metclasses. + + If 'with_base_fields' is True, all fields from the bases are used. + Otherwise, only fields in the 'declared_fields' attribute on the bases are + used. The distinction is useful in ModelForm subclassing. Also integrates any additional media definitions """ - 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)) + 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. + # 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. + if with_base_fields: for base in bases[::-1]: if hasattr(base, 'base_fields'): fields = base.base_fields.items() + fields + else: + for base in bases[::-1]: + if hasattr(base, 'declared_fields'): + fields = base.declared_fields.items() + fields + + return SortedDict(fields) - attrs['base_fields'] = SortedDict(fields) +class DeclarativeFieldsMetaclass(type): + """ + 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): + attrs['base_fields'] = get_declared_fields(bases, attrs) new_class = type.__new__(cls, name, bases, attrs) if 'media' not in attrs: diff --git a/django/newforms/models.py b/django/newforms/models.py index e0f2cde5d4..3d71ee64e5 100644 --- a/django/newforms/models.py +++ b/django/newforms/models.py @@ -11,7 +11,7 @@ from django.utils.datastructures import SortedDict from django.core.exceptions import ImproperlyConfigured from util import ValidationError, ErrorList -from forms import BaseForm +from forms import BaseForm, get_declared_fields from fields import Field, ChoiceField, IntegerField, EMPTY_VALUES from formsets import BaseFormSet, formset_for_form, DELETION_FIELD_NAME from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput @@ -213,57 +213,39 @@ class ModelFormOptions(object): self.fields = getattr(options, 'fields', None) self.exclude = getattr(options, 'exclude', None) + class ModelFormMetaclass(type): def __new__(cls, name, bases, attrs, formfield_callback=lambda f: f.formfield()): - 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 - declared_fields = SortedDict(fields) - - opts = ModelFormOptions(attrs.get('Meta', None)) - attrs['_meta'] = opts - - # Don't allow more than one Meta model defenition in bases. The fields - # would be generated correctly, but the save method won't deal with - # more than one object. - base_models = [] - for base in bases: - base_opts = getattr(base, '_meta', None) - base_model = getattr(base_opts, 'model', None) - if base_model is not None: - base_models.append(base_model) - if len(base_models) > 1: - raise ImproperlyConfigured("%s's base classes define more than one model." % name) + try: + parents = [b for b in bases if issubclass(b, ModelForm)] + except NameError: + # We are defining ModelForm itself. + parents = None + if not parents: + return super(ModelFormMetaclass, cls).__new__(cls, name, bases, + attrs) - # If a model is defined, extract form fields from it and add them to base_fields - if attrs['_meta'].model is not None: - # Don't allow a subclass to define a different Meta model than a - # parent class has. Technically the right fields would be generated, - # but the save method will not deal with more than one model. - for base in bases: - base_opts = getattr(base, '_meta', None) - base_model = getattr(base_opts, 'model', None) - if base_model and base_model is not opts.model: - raise ImproperlyConfigured('%s defines a different model than its parent.' % name) - model_fields = fields_for_model(opts.model, opts.fields, - opts.exclude, formfield_callback) - # fields declared in base classes override fields from the model - model_fields.update(declared_fields) - attrs['base_fields'] = model_fields + new_class = type.__new__(cls, name, bases, attrs) + declared_fields = get_declared_fields(bases, attrs, False) + opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None)) + if opts.model: + # If a model is defined, extract form fields from it. + fields = fields_for_model(opts.model, opts.fields, + opts.exclude, formfield_callback) + # Override default model fields with any custom declared ones + # (plus, include all the other declared fields). + fields.update(declared_fields) else: - attrs['base_fields'] = declared_fields - return type.__new__(cls, name, bases, attrs) + fields = declared_fields + new_class.declared_fields = declared_fields + new_class.base_fields = fields + return new_class class BaseModelForm(BaseForm): def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, - initial=None, error_class=ErrorList, label_suffix=':', instance=None): + initial=None, error_class=ErrorList, label_suffix=':', + instance=None): opts = self._meta if instance is None: # if we didn't get an instance, instantiate a new one @@ -279,7 +261,8 @@ class BaseModelForm(BaseForm): def save(self, commit=True): """ - Saves this ``form``'s cleaned_data into model instance ``self.instance``. + Saves this ``form``'s cleaned_data into model instance + ``self.instance``. If commit=True, then the changes to ``instance`` will be saved to the database. Returns ``instance``. diff --git a/django/newforms/widgets.py b/django/newforms/widgets.py index 4f65ff633a..18b3fa5eb3 100644 --- a/django/newforms/widgets.py +++ b/django/newforms/widgets.py @@ -547,7 +547,7 @@ class MultiWidget(Widget): if id_: final_attrs = dict(final_attrs, id='%s_%s' % (id_, i)) output.append(widget.render(name + '_%s' % i, widget_value, final_attrs)) - return self.format_output(output) + return mark_safe(self.format_output(output)) def id_for_label(self, id_): # See the comment for RadioSelect.id_for_label() |
