diff options
Diffstat (limited to 'tests/modeltests/model_forms/models.py')
| -rw-r--r-- | tests/modeltests/model_forms/models.py | 135 |
1 files changed, 101 insertions, 34 deletions
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py index 7ce89c61a6..657d506b33 100644 --- a/tests/modeltests/model_forms/models.py +++ b/tests/modeltests/model_forms/models.py @@ -6,17 +6,20 @@ model instance. 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, -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 -the database if create(save=True), which is default. If you pass -create(save=False), then you'll get the object without saving it. +the database if save(commit=True), which is default. If you pass +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 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() -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 -get the object without saving it. +other Form, with one additional method: save(). The save() +method updates the model instance. It also takes a commit=True parameter. + +The function django.newforms.save_instance() takes a bound form instance and a +model instance and saves the form's clean_data into the instance. It also takes +a commit=True parameter. """ from django.db import models @@ -29,7 +32,7 @@ class Category(models.Model): return self.name class Writer(models.Model): - name = models.CharField(maxlength=50) + name = models.CharField(maxlength=50, help_text='Use both first and last names.') def __str__(self): return self.name @@ -38,13 +41,14 @@ class Article(models.Model): headline = models.CharField(maxlength=50) pub_date = models.DateField() writer = models.ForeignKey(Writer) + article = models.TextField() 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 +>>> from django.newforms import form_for_model, form_for_instance, save_instance, BaseForm, Form, CharField >>> import datetime >>> Category.objects.all() @@ -67,35 +71,36 @@ __test__ = {'API_TESTS': """ <li>The URL: <input type="text" name="url" maxlength="40" /></li> >>> f = CategoryForm({'name': 'Entertainment', 'url': 'entertainment'}) ->>> f.errors -{} +>>> f.is_valid() +True >>> f.clean_data {'url': u'entertainment', 'name': u'Entertainment'} ->>> obj = f.create() +>>> obj = f.save() >>> obj <Category: Entertainment> >>> Category.objects.all() [<Category: Entertainment>] >>> f = CategoryForm({'name': "It's a test", 'url': 'test'}) ->>> f.errors -{} +>>> f.is_valid() +True >>> f.clean_data {'url': u'test', 'name': u"It's a test"} ->>> obj = f.create() +>>> obj = f.save() >>> obj <Category: It's a test> >>> Category.objects.all() [<Category: Entertainment>, <Category: It's a test>] -If you call create() with save=False, then it will return an object that hasn't -yet been saved. In this case, it's up to you to save it. +If you call save() with commit=False, then it will return an object that +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.errors -{} +>>> f.is_valid() +True >>> f.clean_data {'url': u'third', 'name': u'Third test'} ->>> obj = f.create(save=False) +>>> obj = f.save(commit=False) >>> obj <Category: Third test> >>> Category.objects.all() @@ -104,17 +109,20 @@ yet been saved. In this case, it's up to you to save it. >>> Category.objects.all() [<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.errors {'name': [u'This field is required.']} >>> f.clean_data ->>> f.create() +Traceback (most recent call last): +... +AttributeError: 'CategoryForm' object has no attribute 'clean_data' +>>> f.save() Traceback (most recent call last): ... ValueError: The Category could not be created because the data didn't validate. >>> f = CategoryForm({'name': '', 'url': 'foo'}) ->>> f.create() +>>> f.save() Traceback (most recent call last): ... ValueError: The Category could not be created because the data didn't validate. @@ -137,11 +145,12 @@ represented by a ChoiceField. <option value="1">Mike Royko</option> <option value="2">Bob Woodward</option> </select></td></tr> +<tr><th>Article:</th><td><textarea name="article"></textarea></td></tr> <tr><th>Categories:</th><td><select multiple="multiple" name="categories"> <option value="1">Entertainment</option> <option value="2">It's a test</option> <option value="3">Third test</option> -</select></td></tr> +</select><br /> Hold down "Control", or "Command" on a Mac, to select more than one.</td></tr> You can pass a custom Form class to form_for_model. Make sure it's a subclass of BaseForm, not Form. @@ -153,17 +162,16 @@ subclass of BaseForm, not Form. >>> f.say_hello() hello -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. +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> +<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr> ->>> art = Article(headline='Test article', pub_date=datetime.date(1988, 1, 4), writer=w) +>>> art = Article(headline='Test article', pub_date=datetime.date(1988, 1, 4), writer=w, article='Hello.') >>> art.save() >>> art.id 1 @@ -177,15 +185,16 @@ the Form gets an apply_changes() method instead of a create() method. <option value="1" selected="selected">Mike Royko</option> <option value="2">Bob Woodward</option> </select></li> +<li>Article: <textarea name="article">Hello.</textarea></li> <li>Categories: <select multiple="multiple" name="categories"> <option value="1">Entertainment</option> <option value="2">It'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'}) +</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> +>>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 'writer': u'1', 'article': 'Hello.'}) >>> f.is_valid() True ->>> new_art = f.apply_changes() +>>> new_art = f.save() >>> new_art.id 1 >>> new_art = Article.objects.get(id=1) @@ -208,10 +217,68 @@ Add some categories and test the many-to-many form output. <option value="1" selected="selected">Mike Royko</option> <option value="2">Bob Woodward</option> </select></li> +<li>Article: <textarea name="article">Hello.</textarea></li> <li>Categories: <select multiple="multiple" name="categories"> <option value="1" selected="selected">Entertainment</option> <option value="2">It's a test</option> <option value="3">Third test</option> -</select></li> +</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> + +>>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', +... 'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']}) +>>> new_art = f.save() +>>> new_art.id +1 +>>> new_art = Article.objects.get(id=1) +>>> new_art.categories.all() +[<Category: Entertainment>, <Category: It's a test>] + +Now, submit form data with no categories. This deletes the existing categories. +>>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', +... 'writer': u'1', 'article': u'Hello.'}) +>>> new_art = f.save() +>>> new_art.id +1 +>>> new_art = Article.objects.get(id=1) +>>> new_art.categories.all() +[] +Create a new article, with categories, via the form. +>>> ArticleForm = form_for_model(Article) +>>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', +... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']}) +>>> new_art = f.save() +>>> new_art.id +2 +>>> new_art = Article.objects.get(id=2) +>>> new_art.categories.all() +[<Category: Entertainment>, <Category: It's a test>] + +Create a new article, with no categories, via the form. +>>> ArticleForm = form_for_model(Article) +>>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', +... 'writer': u'1', 'article': u'Test.'}) +>>> new_art = f.save() +>>> new_art.id +3 +>>> new_art = Article.objects.get(id=3) +>>> new_art.categories.all() +[] + +Here, we define a custom Form. Because it happens to have the same fields as +the Category model, we can use save_instance() to apply its changes to an +existing Category instance. +>>> class ShortCategory(Form): +... name = CharField(max_length=5) +... url = CharField(max_length=3) +>>> cat = Category.objects.get(name='Third test') +>>> cat +<Category: Third test> +>>> cat.id +3 +>>> sc = ShortCategory({'name': 'Third', 'url': '3rd'}) +>>> save_instance(sc, cat) +<Category: Third> +>>> Category.objects.get(id=3) +<Category: Third> """} |
