summaryrefslogtreecommitdiff
path: root/django/newforms
diff options
context:
space:
mode:
authorJoseph Kocherhans <joseph@jkocherhans.com>2008-02-15 17:05:48 +0000
committerJoseph Kocherhans <joseph@jkocherhans.com>2008-02-15 17:05:48 +0000
commit7c1242a7a3a62bc63715bc47400827d4cf3c5e05 (patch)
tree357594e407b6115ebc4419f2003f3c3282eca344 /django/newforms
parentdaa467d79ec7b40e376294eabc51222a67690181 (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.py2
-rw-r--r--django/newforms/forms.py37
-rw-r--r--django/newforms/models.py73
-rw-r--r--django/newforms/widgets.py2
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()