newforms: Implemented form_for_instance(). The resulting Form class does not yet have a method that saves the changes
git-svn-id: http://code.djangoproject.com/svn/django/trunk@4250 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
2cb0fe71a2
commit
71ce11f617
|
@ -334,10 +334,10 @@ class Field(object):
|
||||||
return self._choices
|
return self._choices
|
||||||
choices = property(_get_choices)
|
choices = property(_get_choices)
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
"Returns a django.newforms.Field instance for this database Field."
|
"Returns a django.newforms.Field instance for this database Field."
|
||||||
# TODO: This is just a temporary default during development.
|
# TODO: This is just a temporary default during development.
|
||||||
return forms.CharField(required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.CharField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class AutoField(Field):
|
class AutoField(Field):
|
||||||
empty_strings_allowed = False
|
empty_strings_allowed = False
|
||||||
|
@ -375,7 +375,7 @@ class AutoField(Field):
|
||||||
super(AutoField, self).contribute_to_class(cls, name)
|
super(AutoField, self).contribute_to_class(cls, name)
|
||||||
cls._meta.has_auto_field = True
|
cls._meta.has_auto_field = True
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
class BooleanField(Field):
|
class BooleanField(Field):
|
||||||
|
@ -392,8 +392,8 @@ class BooleanField(Field):
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.CheckboxField]
|
return [oldforms.CheckboxField]
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.BooleanField(required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.BooleanField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class CharField(Field):
|
class CharField(Field):
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
|
@ -409,8 +409,8 @@ class CharField(Field):
|
||||||
raise validators.ValidationError, gettext_lazy("This field cannot be null.")
|
raise validators.ValidationError, gettext_lazy("This field cannot be null.")
|
||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.CharField(max_length=self.maxlength, required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.CharField(max_length=self.maxlength, required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
# TODO: Maybe move this into contrib, because it's specialized.
|
# TODO: Maybe move this into contrib, because it's specialized.
|
||||||
class CommaSeparatedIntegerField(CharField):
|
class CommaSeparatedIntegerField(CharField):
|
||||||
|
@ -483,8 +483,8 @@ class DateField(Field):
|
||||||
val = self._get_val_from_obj(obj)
|
val = self._get_val_from_obj(obj)
|
||||||
return {self.attname: (val is not None and val.strftime("%Y-%m-%d") or '')}
|
return {self.attname: (val is not None and val.strftime("%Y-%m-%d") or '')}
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.DateField(required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.DateField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class DateTimeField(DateField):
|
class DateTimeField(DateField):
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
|
@ -544,8 +544,8 @@ class DateTimeField(DateField):
|
||||||
return {date_field: (val is not None and val.strftime("%Y-%m-%d") or ''),
|
return {date_field: (val is not None and val.strftime("%Y-%m-%d") or ''),
|
||||||
time_field: (val is not None and val.strftime("%H:%M:%S") or '')}
|
time_field: (val is not None and val.strftime("%H:%M:%S") or '')}
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.DateTimeField(required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.DateTimeField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class EmailField(CharField):
|
class EmailField(CharField):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -561,8 +561,8 @@ class EmailField(CharField):
|
||||||
def validate(self, field_data, all_data):
|
def validate(self, field_data, all_data):
|
||||||
validators.isValidEmail(field_data, all_data)
|
validators.isValidEmail(field_data, all_data)
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.EmailField(required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.EmailField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class FileField(Field):
|
class FileField(Field):
|
||||||
def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):
|
def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):
|
||||||
|
@ -696,8 +696,8 @@ class IntegerField(Field):
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.IntegerField]
|
return [oldforms.IntegerField]
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.IntegerField(required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.IntegerField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class IPAddressField(Field):
|
class IPAddressField(Field):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -793,8 +793,8 @@ class TimeField(Field):
|
||||||
val = self._get_val_from_obj(obj)
|
val = self._get_val_from_obj(obj)
|
||||||
return {self.attname: (val is not None and val.strftime("%H:%M:%S") or '')}
|
return {self.attname: (val is not None and val.strftime("%H:%M:%S") or '')}
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.TimeField(required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.TimeField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class URLField(Field):
|
class URLField(Field):
|
||||||
def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
|
def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
|
||||||
|
@ -806,8 +806,8 @@ class URLField(Field):
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.URLField]
|
return [oldforms.URLField]
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.URLField(required=not self.blank, verify_exists=self.verify_exists, label=capfirst(self.verbose_name))
|
return forms.URLField(required=not self.blank, verify_exists=self.verify_exists, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class USStateField(Field):
|
class USStateField(Field):
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
|
|
|
@ -548,8 +548,8 @@ class ForeignKey(RelatedField, Field):
|
||||||
def contribute_to_related_class(self, cls, related):
|
def contribute_to_related_class(self, cls, related):
|
||||||
setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
|
setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.ChoiceField(choices=self.get_choices_default(), required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.ChoiceField(choices=self.get_choices_default(), required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class OneToOneField(RelatedField, IntegerField):
|
class OneToOneField(RelatedField, IntegerField):
|
||||||
def __init__(self, to, to_field=None, **kwargs):
|
def __init__(self, to, to_field=None, **kwargs):
|
||||||
|
@ -612,8 +612,8 @@ class OneToOneField(RelatedField, IntegerField):
|
||||||
if not cls._meta.one_to_one_field:
|
if not cls._meta.one_to_one_field:
|
||||||
cls._meta.one_to_one_field = self
|
cls._meta.one_to_one_field = self
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.ChoiceField(choices=self.get_choices_default(), required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.ChoiceField(choices=self.get_choices_default(), required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class ManyToManyField(RelatedField, Field):
|
class ManyToManyField(RelatedField, Field):
|
||||||
def __init__(self, to, **kwargs):
|
def __init__(self, to, **kwargs):
|
||||||
|
@ -721,8 +721,8 @@ class ManyToManyField(RelatedField, Field):
|
||||||
def set_attributes_from_rel(self):
|
def set_attributes_from_rel(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def formfield(self):
|
def formfield(self, initial=None):
|
||||||
return forms.MultipleChoiceField(choices=self.get_choices_default(), required=not self.blank, label=capfirst(self.verbose_name))
|
return forms.MultipleChoiceField(choices=self.get_choices_default(), required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
|
||||||
|
|
||||||
class ManyToOneRel(object):
|
class ManyToOneRel(object):
|
||||||
def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
|
def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
|
||||||
|
|
|
@ -5,10 +5,14 @@ and database field objects.
|
||||||
|
|
||||||
from forms import BaseForm, DeclarativeFieldsMetaclass, SortedDictFromList
|
from forms import BaseForm, DeclarativeFieldsMetaclass, SortedDictFromList
|
||||||
|
|
||||||
__all__ = ('form_for_model', 'form_for_fields')
|
__all__ = ('form_for_model', 'form_for_instance', 'form_for_fields')
|
||||||
|
|
||||||
def create(self, save=True):
|
def create(self, save=True):
|
||||||
"Creates and returns model instance according to self.clean_data."
|
"""
|
||||||
|
Creates and returns model instance according to self.clean_data.
|
||||||
|
|
||||||
|
This method is created for any form_for_model Form.
|
||||||
|
"""
|
||||||
if self.errors:
|
if self.errors:
|
||||||
raise ValueError("The %s could not be created because the data didn't validate." % self._model._meta.object_name)
|
raise ValueError("The %s could not be created because the data didn't validate." % self._model._meta.object_name)
|
||||||
obj = self._model(**self.clean_data)
|
obj = self._model(**self.clean_data)
|
||||||
|
@ -16,7 +20,7 @@ def create(self, save=True):
|
||||||
obj.save()
|
obj.save()
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def form_for_model(model, form=None):
|
def form_for_model(model, form=BaseForm):
|
||||||
"""
|
"""
|
||||||
Returns a Form class for the given Django model class.
|
Returns a Form class for the given Django model class.
|
||||||
|
|
||||||
|
@ -29,9 +33,25 @@ def form_for_model(model, form=None):
|
||||||
if formfield:
|
if formfield:
|
||||||
field_list.append((f.name, formfield))
|
field_list.append((f.name, formfield))
|
||||||
fields = SortedDictFromList(field_list)
|
fields = SortedDictFromList(field_list)
|
||||||
form = form or BaseForm
|
|
||||||
return type(opts.object_name + 'Form', (form,), {'fields': fields, '_model': model, 'create': create})
|
return type(opts.object_name + 'Form', (form,), {'fields': fields, '_model': model, 'create': create})
|
||||||
|
|
||||||
|
def form_for_instance(instance, form=BaseForm):
|
||||||
|
"""
|
||||||
|
Returns a Form class for the given Django model instance.
|
||||||
|
|
||||||
|
Provide 'form' if you want to use a custom BaseForm subclass.
|
||||||
|
"""
|
||||||
|
model = instance.__class__
|
||||||
|
opts = model._meta
|
||||||
|
field_list = []
|
||||||
|
for f in opts.fields + opts.many_to_many:
|
||||||
|
current_value = getattr(instance, f.attname)
|
||||||
|
formfield = f.formfield(initial=current_value)
|
||||||
|
if formfield:
|
||||||
|
field_list.append((f.name, formfield))
|
||||||
|
fields = SortedDictFromList(field_list)
|
||||||
|
return type(opts.object_name + 'InstanceForm', (form,), {'fields': fields, '_model': model})
|
||||||
|
|
||||||
def form_for_fields(field_list):
|
def form_for_fields(field_list):
|
||||||
"Returns a Form class for the given list of Django database field instances."
|
"Returns a Form class for the given list of Django database field instances."
|
||||||
fields = SortedDictFromList([(f.name, f.formfield()) for f in field_list])
|
fields = SortedDictFromList([(f.name, f.formfield()) for f in field_list])
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Article(models.Model):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
__test__ = {'API_TESTS': """
|
__test__ = {'API_TESTS': """
|
||||||
>>> from django.newforms import form_for_model, BaseForm
|
>>> from django.newforms import form_for_model, form_for_instance, BaseForm
|
||||||
|
|
||||||
>>> Category.objects.all()
|
>>> Category.objects.all()
|
||||||
[]
|
[]
|
||||||
|
@ -141,4 +141,13 @@ subclass of BaseForm, not Form.
|
||||||
>>> f = CategoryForm()
|
>>> f = CategoryForm()
|
||||||
>>> f.say_hello()
|
>>> f.say_hello()
|
||||||
hello
|
hello
|
||||||
|
|
||||||
|
Use form_for_instance to create a Form from a model instance. The difference
|
||||||
|
between this Form and one created via form_for_model is that the object's
|
||||||
|
current values are inserted as 'initial' data in each Field.
|
||||||
|
>>> w = Writer.objects.get(name='Mike Royko')
|
||||||
|
>>> RoykoForm = form_for_instance(w)
|
||||||
|
>>> f = RoykoForm(auto_id=False)
|
||||||
|
>>> print f
|
||||||
|
<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /></td></tr>
|
||||||
"""}
|
"""}
|
||||||
|
|
Loading…
Reference in New Issue