newforms: Changed model auto-Form generation so that create() and apply_changes() are now both called save() -- for the purposes of simplicity

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4299 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2007-01-09 05:22:48 +00:00
parent fb60a6ff0a
commit d08112a6a7
2 changed files with 28 additions and 27 deletions

View File

@ -7,7 +7,7 @@ from forms import BaseForm, DeclarativeFieldsMetaclass, SortedDictFromList
__all__ = ('form_for_model', 'form_for_instance', 'form_for_fields') __all__ = ('form_for_model', 'form_for_instance', 'form_for_fields')
def create(self, save=True): def model_save(self, commit=True):
""" """
Creates and returns model instance according to self.clean_data. Creates and returns model instance according to self.clean_data.
@ -16,14 +16,14 @@ def create(self, save=True):
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)
if save: if commit:
obj.save() obj.save()
return obj return obj
def make_apply_changes(opts, instance): def make_instance_save(opts, instance):
"Returns the apply_changes() method for a form_for_instance Form." "Returns the save() method for a form_for_instance Form."
from django.db import models from django.db import models
def apply_changes(self, save=True): def apply_changes(self, commit=True):
if self.errors: if self.errors:
raise ValueError("The %s could not be changed because the data didn't validate." % opts.object_name) raise ValueError("The %s could not be changed because the data didn't validate." % opts.object_name)
clean_data = self.clean_data clean_data = self.clean_data
@ -31,7 +31,7 @@ def make_apply_changes(opts, instance):
if isinstance(f, models.AutoField): if isinstance(f, models.AutoField):
continue continue
setattr(instance, f.attname, clean_data[f.name]) setattr(instance, f.attname, clean_data[f.name])
if save: if commit:
instance.save() instance.save()
return instance return instance
return apply_changes return apply_changes
@ -49,7 +49,7 @@ def form_for_model(model, form=BaseForm):
if formfield: if formfield:
field_list.append((f.name, formfield)) field_list.append((f.name, formfield))
fields = SortedDictFromList(field_list) fields = SortedDictFromList(field_list)
return type(opts.object_name + 'Form', (form,), {'fields': fields, '_model': model, 'create': create}) return type(opts.object_name + 'Form', (form,), {'fields': fields, '_model': model, 'save': model_save})
def form_for_instance(instance, form=BaseForm): def form_for_instance(instance, form=BaseForm):
""" """
@ -67,7 +67,7 @@ def form_for_instance(instance, form=BaseForm):
field_list.append((f.name, formfield)) field_list.append((f.name, formfield))
fields = SortedDictFromList(field_list) fields = SortedDictFromList(field_list)
return type(opts.object_name + 'InstanceForm', (form,), return type(opts.object_name + 'InstanceForm', (form,),
{'fields': fields, '_model': model, 'apply_changes': make_apply_changes(opts, instance)}) {'fields': fields, '_model': model, 'save': make_instance_save(opts, instance)})
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."

View File

@ -6,17 +6,18 @@ model instance.
The function django.newforms.form_for_model() takes a model class and returns The function django.newforms.form_for_model() takes a model class and returns
a Form that is tied to the model. This Form works just like any other Form, a Form that is tied to the model. This Form works just like any other Form,
with one additional method: create(). The create() method creates an instance with one additional method: save(). The save() method creates an instance
of the model and returns that newly created instance. It saves the instance to of the model and returns that newly created instance. It saves the instance to
the database if create(save=True), which is default. If you pass the database if save(commit=True), which is default. If you pass
create(save=False), then you'll get the object without saving it. commit=False, then you'll get the object without committing the changes to the
database.
The function django.newforms.form_for_instance() takes a model instance and The function django.newforms.form_for_instance() takes a model instance and
returns a Form that is tied to the instance. This form works just like any returns a Form that is tied to the instance. This form works just like any
other Form, with one additional method: apply_changes(). The apply_changes() other Form, with one additional method: save(). The save()
method updates the model instance. It saves the changes to the database if method updates the model instance. It saves the changes to the database if
apply_changes(save=True), which is default. If you pass save=False, then you'll save(commit=True), which is default. If you pass commit=False, then you'll
get the object without saving it. get the object without committing the changes to the database.
""" """
from django.db import models from django.db import models
@ -71,7 +72,7 @@ __test__ = {'API_TESTS': """
True True
>>> f.clean_data >>> f.clean_data
{'url': u'entertainment', 'name': u'Entertainment'} {'url': u'entertainment', 'name': u'Entertainment'}
>>> obj = f.create() >>> obj = f.save()
>>> obj >>> obj
<Category: Entertainment> <Category: Entertainment>
>>> Category.objects.all() >>> Category.objects.all()
@ -82,20 +83,21 @@ True
True True
>>> f.clean_data >>> f.clean_data
{'url': u'test', 'name': u"It's a test"} {'url': u'test', 'name': u"It's a test"}
>>> obj = f.create() >>> obj = f.save()
>>> obj >>> obj
<Category: It's a test> <Category: It's a test>
>>> Category.objects.all() >>> Category.objects.all()
[<Category: Entertainment>, <Category: It's a test>] [<Category: Entertainment>, <Category: It's a test>]
If you call create() with save=False, then it will return an object that hasn't If you call save() with commit=False, then it will return an object that
yet been saved. In this case, it's up to you to save it. hasn't yet been saved to the database. In this case, it's up to you to call
save() on the resulting model instance.
>>> f = CategoryForm({'name': 'Third test', 'url': 'third'}) >>> f = CategoryForm({'name': 'Third test', 'url': 'third'})
>>> f.is_valid() >>> f.is_valid()
True True
>>> f.clean_data >>> f.clean_data
{'url': u'third', 'name': u'Third test'} {'url': u'third', 'name': u'Third test'}
>>> obj = f.create(save=False) >>> obj = f.save(commit=False)
>>> obj >>> obj
<Category: Third test> <Category: Third test>
>>> Category.objects.all() >>> Category.objects.all()
@ -104,7 +106,7 @@ True
>>> Category.objects.all() >>> Category.objects.all()
[<Category: Entertainment>, <Category: It's a test>, <Category: Third test>] [<Category: Entertainment>, <Category: It's a test>, <Category: Third test>]
If you call create() with invalid data, you'll get a ValueError. If you call save() with invalid data, you'll get a ValueError.
>>> f = CategoryForm({'name': '', 'url': 'foo'}) >>> f = CategoryForm({'name': '', 'url': 'foo'})
>>> f.errors >>> f.errors
{'name': [u'This field is required.']} {'name': [u'This field is required.']}
@ -112,12 +114,12 @@ If you call create() with invalid data, you'll get a ValueError.
Traceback (most recent call last): Traceback (most recent call last):
... ...
AttributeError: 'CategoryForm' object has no attribute 'clean_data' AttributeError: 'CategoryForm' object has no attribute 'clean_data'
>>> f.create() >>> f.save()
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: The Category could not be created because the data didn't validate. ValueError: The Category could not be created because the data didn't validate.
>>> f = CategoryForm({'name': '', 'url': 'foo'}) >>> f = CategoryForm({'name': '', 'url': 'foo'})
>>> f.create() >>> f.save()
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: The Category could not be created because the data didn't validate. ValueError: The Category could not be created because the data didn't validate.
@ -156,10 +158,9 @@ subclass of BaseForm, not Form.
>>> f.say_hello() >>> f.say_hello()
hello hello
Use form_for_instance to create a Form from a model instance. There are two Use form_for_instance to create a Form from a model instance. The difference
differences between this Form and one created via form_for_model. First, the between this Form and one created via form_for_model is that the object's
object's current values are inserted as 'initial' data in each Field. Second, current values are inserted as 'initial' data in each Field.
the Form gets an apply_changes() method instead of a create() method.
>>> w = Writer.objects.get(name='Mike Royko') >>> w = Writer.objects.get(name='Mike Royko')
>>> RoykoForm = form_for_instance(w) >>> RoykoForm = form_for_instance(w)
>>> f = RoykoForm(auto_id=False) >>> f = RoykoForm(auto_id=False)
@ -188,7 +189,7 @@ the Form gets an apply_changes() method instead of a create() method.
>>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 'writer': u'1'}) >>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 'writer': u'1'})
>>> f.is_valid() >>> f.is_valid()
True True
>>> new_art = f.apply_changes() >>> new_art = f.save()
>>> new_art.id >>> new_art.id
1 1
>>> new_art = Article.objects.get(id=1) >>> new_art = Article.objects.get(id=1)