summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Holovaty <adrian@holovaty.com>2006-12-28 02:34:53 +0000
committerAdrian Holovaty <adrian@holovaty.com>2006-12-28 02:34:53 +0000
commitbcb7a31b2c6ca26906298725cc830bbfb0c4b383 (patch)
treecae06b0bc0d9c8d0418374128c1c0073c4ac376e
parent34dce706ee9ac30d950d95e1647aadbed2a70921 (diff)
newforms: Implemented apply_changes() method for form_for_instance Forms
git-svn-id: http://code.djangoproject.com/svn/django/trunk@4253 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/newforms/models.py21
-rw-r--r--tests/modeltests/model_forms/models.py39
2 files changed, 54 insertions, 6 deletions
diff --git a/django/newforms/models.py b/django/newforms/models.py
index 12acc0ac83..e000e394e1 100644
--- a/django/newforms/models.py
+++ b/django/newforms/models.py
@@ -20,6 +20,22 @@ def create(self, save=True):
obj.save()
return obj
+def make_apply_changes(opts, instance):
+ "Returns the apply_changes() method for a form_for_instance Form."
+ from django.db import models
+ def apply_changes(self, save=True):
+ if self.errors:
+ raise ValueError("The %s could not be changed because the data didn't validate." % opts.object_name)
+ clean_data = self.clean_data
+ for f in opts.fields + opts.many_to_many:
+ if isinstance(f, models.AutoField):
+ continue
+ setattr(instance, f.attname, clean_data[f.name])
+ if save:
+ instance.save()
+ return instance
+ return apply_changes
+
def form_for_model(model, form=BaseForm):
"""
Returns a Form class for the given Django model class.
@@ -45,12 +61,13 @@ def form_for_instance(instance, form=BaseForm):
opts = model._meta
field_list = []
for f in opts.fields + opts.many_to_many:
- current_value = getattr(instance, f.attname)
+ current_value = f.value_from_object(instance)
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})
+ return type(opts.object_name + 'InstanceForm', (form,),
+ {'fields': fields, '_model': model, 'apply_changes': make_apply_changes(opts, instance)})
def form_for_fields(field_list):
"Returns a Form class for the given list of Django database field instances."
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py
index 8ae9ddc6fb..60a3defde5 100644
--- a/tests/modeltests/model_forms/models.py
+++ b/tests/modeltests/model_forms/models.py
@@ -30,13 +30,14 @@ class Article(models.Model):
headline = models.CharField(maxlength=50)
pub_date = models.DateTimeField()
writer = models.ForeignKey(Writer)
- categories = models.ManyToManyField(Category)
+ categories = models.ManyToManyField(Category, blank=True)
def __str__(self):
return self.headline
__test__ = {'API_TESTS': """
>>> from django.newforms import form_for_model, form_for_instance, BaseForm
+>>> import datetime
>>> Category.objects.all()
[]
@@ -142,12 +143,42 @@ subclass of BaseForm, not Form.
>>> f.say_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.
+Use form_for_instance to create a Form from a model instance. There are two
+differences between this Form and one created via form_for_model. First, the
+object's current values are inserted as 'initial' data in each Field. Second,
+the Form gets an apply_changes() method instead of a create() method.
>>> 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>
+
+>>> art = Article(headline='Test article', pub_date=datetime.date(1988, 1, 4), writer=w)
+>>> art.save()
+>>> art.id
+1
+>>> TestArticleForm = form_for_instance(art)
+>>> f = TestArticleForm(auto_id=False)
+>>> print f.as_ul()
+<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li>
+<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
+<li>Writer: <select name="writer">
+<option value="">---------</option>
+<option value="1" selected="selected">Mike Royko</option>
+<option value="2">Bob Woodward</option>
+</select></li>
+<li>Categories: <select multiple="multiple" name="categories">
+<option value="1">Entertainment</option>
+<option value="2">It&#39;s a test</option>
+<option value="3">Third test</option>
+</select></li>
+>>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 'writer': u'1'})
+>>> f.is_valid()
+True
+>>> new_art = f.apply_changes()
+>>> new_art.id
+1
+>>> new_art = Article.objects.get(id=1)
+>>> new_art.headline
+'New headline'
"""}