Code

Ticket #6162: modelform-init.diff

File modelform-init.diff, 13.2 KB (added by ubernostrum, 7 years ago)

Patch which "fixes" ModelForm.__init__()

Line 
1Index: django/newforms/models.py
2===================================================================
3--- django/newforms/models.py   (revision 6898)
4+++ django/newforms/models.py   (working copy)
5@@ -262,11 +262,15 @@
6         return type.__new__(cls, name, bases, attrs)
7 
8 class BaseModelForm(BaseForm):
9-    def __init__(self, instance, data=None, files=None, auto_id='id_%s', prefix=None,
10-                 initial=None, error_class=ErrorList, label_suffix=':'):
11-        self.instance = instance
12+    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
13+                 initial=None, error_class=ErrorList, label_suffix=':', instance=None):
14         opts = self._meta
15-        object_data = model_to_dict(instance, opts.fields, opts.exclude)
16+        if instance is None:
17+           self.instance = opts.model()
18+           object_data = {}
19+        else:
20+            self.instance = instance
21+            object_data = model_to_dict(instance, opts.fields, opts.exclude)
22         # if initial was provided, it should override the values from instance
23         if initial is not None:
24             object_data.update(initial)
25Index: tests/modeltests/model_forms/models.py
26===================================================================
27--- tests/modeltests/model_forms/models.py      (revision 6898)
28+++ tests/modeltests/model_forms/models.py      (working copy)
29@@ -156,7 +156,7 @@
30 ImproperlyConfigured: BadForm's base classes define more than one model.
31 
32 
33-# Old form_for_x tests #######################################################
34+# Test valid ModelForms #######################################################
35 
36 >>> from django.newforms import ModelForm, CharField
37 >>> import datetime
38@@ -167,7 +167,7 @@
39 >>> class CategoryForm(ModelForm):
40 ...     class Meta:
41 ...         model = Category
42->>> f = CategoryForm(Category())
43+>>> f = CategoryForm()
44 >>> print f
45 <tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
46 <tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr>
47@@ -179,13 +179,13 @@
48 >>> print f['name']
49 <input id="id_name" type="text" name="name" maxlength="20" />
50 
51->>> f = CategoryForm(Category(), auto_id=False)
52+>>> f = CategoryForm(auto_id=False)
53 >>> print f.as_ul()
54 <li>Name: <input type="text" name="name" maxlength="20" /></li>
55 <li>Slug: <input type="text" name="slug" maxlength="20" /></li>
56 <li>The URL: <input type="text" name="url" maxlength="40" /></li>
57 
58->>> f = CategoryForm(Category(), {'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'})
59+>>> f = CategoryForm({'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'})
60 >>> f.is_valid()
61 True
62 >>> f.cleaned_data
63@@ -196,7 +196,7 @@
64 >>> Category.objects.all()
65 [<Category: Entertainment>]
66 
67->>> f = CategoryForm(Category(), {'name': "It's a test", 'slug': 'its-test', 'url': 'test'})
68+>>> f = CategoryForm({'name': "It's a test", 'slug': 'its-test', 'url': 'test'})
69 >>> f.is_valid()
70 True
71 >>> f.cleaned_data
72@@ -210,7 +210,7 @@
73 If you call save() with commit=False, then it will return an object that
74 hasn't yet been saved to the database. In this case, it's up to you to call
75 save() on the resulting model instance.
76->>> f = CategoryForm(Category(), {'name': 'Third test', 'slug': 'third-test', 'url': 'third'})
77+>>> f = CategoryForm({'name': 'Third test', 'slug': 'third-test', 'url': 'third'})
78 >>> f.is_valid()
79 True
80 >>> f.cleaned_data
81@@ -225,7 +225,7 @@
82 [<Category: Entertainment>, <Category: It's a test>, <Category: Third test>]
83 
84 If you call save() with invalid data, you'll get a ValueError.
85->>> f = CategoryForm(Category(), {'name': '', 'slug': '', 'url': 'foo'})
86+>>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'})
87 >>> f.errors
88 {'name': [u'This field is required.'], 'slug': [u'This field is required.']}
89 >>> f.cleaned_data
90@@ -236,7 +236,7 @@
91 Traceback (most recent call last):
92 ...
93 ValueError: The Category could not be created because the data didn't validate.
94->>> f = CategoryForm(Category(), {'name': '', 'slug': '', 'url': 'foo'})
95+>>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'})
96 >>> f.save()
97 Traceback (most recent call last):
98 ...
99@@ -253,7 +253,7 @@
100 >>> class ArticleForm(ModelForm):
101 ...     class Meta:
102 ...         model = Article
103->>> f = ArticleForm(Article(), auto_id=False)
104+>>> f = ArticleForm(auto_id=False)
105 >>> print f
106 <tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
107 <tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr>
108@@ -286,7 +286,7 @@
109 ...     class Meta:
110 ...         model = Article
111 ...         fields = ('headline','pub_date')
112->>> f = PartialArticleForm(Article(), auto_id=False)
113+>>> f = PartialArticleForm(auto_id=False)
114 >>> print f
115 <tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
116 <tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
117@@ -298,7 +298,7 @@
118 >>> class RoykoForm(ModelForm):
119 ...     class Meta:
120 ...         model = Writer
121->>> f = RoykoForm(w, auto_id=False)
122+>>> f = RoykoForm(auto_id=False, instance=w)
123 >>> print f
124 <tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr>
125 
126@@ -309,7 +309,7 @@
127 >>> class TestArticleForm(ModelForm):
128 ...     class Meta:
129 ...         model = Article
130->>> f = TestArticleForm(art, auto_id=False)
131+>>> f = TestArticleForm(instance=art, auto_id=False)
132 >>> print f.as_ul()
133 <li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li>
134 <li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li>
135@@ -331,7 +331,7 @@
136 <option value="2">It&#39;s a test</option>
137 <option value="3">Third test</option>
138 </select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li>
139->>> f = TestArticleForm(art, {'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'})
140+>>> f = TestArticleForm({'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'}, instance=art)
141 >>> f.is_valid()
142 True
143 >>> test_art = f.save()
144@@ -347,7 +347,7 @@
145 ...     class Meta:
146 ...         model = Article
147 ...         fields=('headline', 'slug', 'pub_date')
148->>> f = PartialArticleForm(art, {'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False)
149+>>> f = PartialArticleForm({'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False, instance=art)
150 >>> print f.as_ul()
151 <li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
152 <li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
153@@ -370,7 +370,7 @@
154 >>> class TestArticleForm(ModelForm):
155 ...     class Meta:
156 ...         model = Article
157->>> f = TestArticleForm(new_art, auto_id=False)
158+>>> f = TestArticleForm(auto_id=False, instance=new_art)
159 >>> print f.as_ul()
160 <li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
161 <li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li>
162@@ -393,8 +393,8 @@
163 <option value="3">Third test</option>
164 </select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li>
165 
166->>> f = TestArticleForm(new_art, {'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
167-...     'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']})
168+>>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
169+...     'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']}, instance=new_art)
170 >>> new_art = f.save()
171 >>> new_art.id
172 1
173@@ -403,8 +403,8 @@
174 [<Category: Entertainment>, <Category: It's a test>]
175 
176 Now, submit form data with no categories. This deletes the existing categories.
177->>> f = TestArticleForm(new_art, {'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
178-...     'writer': u'1', 'article': u'Hello.'})
179+>>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',
180+...     'writer': u'1', 'article': u'Hello.'}, instance=new_art)
181 >>> new_art = f.save()
182 >>> new_art.id
183 1
184@@ -416,7 +416,7 @@
185 >>> class ArticleForm(ModelForm):
186 ...     class Meta:
187 ...         model = Article
188->>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
189+>>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
190 ...     'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']})
191 >>> new_art = f.save()
192 >>> new_art.id
193@@ -429,7 +429,7 @@
194 >>> class ArticleForm(ModelForm):
195 ...     class Meta:
196 ...         model = Article
197->>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
198+>>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',
199 ...     'writer': u'1', 'article': u'Test.'})
200 >>> new_art = f.save()
201 >>> new_art.id
202@@ -443,7 +443,7 @@
203 >>> class ArticleForm(ModelForm):
204 ...     class Meta:
205 ...         model = Article
206->>> f = ArticleForm(Article(), {'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01',
207+>>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01',
208 ...     'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']})
209 >>> new_art = f.save(commit=False)
210 
211@@ -474,7 +474,7 @@
212 <Category: Third test>
213 >>> cat.id
214 3
215->>> form = ShortCategory(cat, {'name': 'Third', 'slug': 'third', 'url': '3rd'})
216+>>> form = ShortCategory({'name': 'Third', 'slug': 'third', 'url': '3rd'}, instance=cat)
217 >>> form.save()
218 <Category: Third>
219 >>> Category.objects.get(id=3)
220@@ -486,7 +486,7 @@
221 >>> class ArticleForm(ModelForm):
222 ...     class Meta:
223 ...         model = Article
224->>> f = ArticleForm(Article(), auto_id=False)
225+>>> f = ArticleForm(auto_id=False)
226 >>> print f.as_ul()
227 <li>Headline: <input type="text" name="headline" maxlength="50" /></li>
228 <li>Slug: <input type="text" name="slug" maxlength="50" /></li>
229@@ -690,7 +690,7 @@
230 >>> class PhoneNumberForm(ModelForm):
231 ...     class Meta:
232 ...         model = PhoneNumber
233->>> f = PhoneNumberForm(PhoneNumber(), {'phone': '(312) 555-1212', 'description': 'Assistance'})
234+>>> f = PhoneNumberForm({'phone': '(312) 555-1212', 'description': 'Assistance'})
235 >>> f.is_valid()
236 True
237 >>> f.cleaned_data
238Index: docs/modelforms.txt
239===================================================================
240--- docs/modelforms.txt (revision 6898)
241+++ docs/modelforms.txt (working copy)
242@@ -24,12 +24,11 @@
243     ...         model = Article
244 
245     # Creating a form to add an article.
246-    >>> article = Article()
247-    >>> form = ArticleForm(article)
248+    >>> form = ArticleForm()
249 
250     # Creating a form to change an existing article.
251     >>> article = Article.objects.get(pk=1)
252-    >>> form = ArticleForm(article)
253+    >>> form = ArticleForm(instance=article)
254 
255 Field types
256 -----------
257@@ -166,18 +165,23 @@
258 The ``save()`` method
259 ---------------------
260 
261-Every form produced by ``ModelForm`` also has a ``save()`` method. This
262-method creates and saves a database object from the data bound to the form.
263-A subclass of ``ModelForm`` also requires a model instance as the first
264-arument to its constructor. For example::
265+Every form produced by ``ModelForm`` also has a ``save()``
266+method. This method creates and saves a database object from the data
267+bound to the form. A subclass of ``ModelForm`` can accept an existing
268+model instance as the keyword argument ``instance``; if this is
269+supplied, ``save()`` will update that instance. If it's not supplied,
270+``save()`` will create a new instance of the specified model::
271 
272     # Create a form instance from POST data.
273-    >>> a = Article()
274-    >>> f = ArticleForm(a, request.POST)
275+    >>> f = ArticleForm(request.POST)
276 
277     # Save a new Article object from the form's data.
278     >>> new_article = f.save()
279 
280+    # Create a form to edit an existing Article.
281+    >>> a = Article.objects.get(pk=1)
282+    >>> f = ArticleForm(instance=a)
283+
284 Note that ``save()`` will raise a ``ValueError`` if the data in the form
285 doesn't validate -- i.e., ``if form.errors``.
286 
287@@ -201,8 +205,7 @@
288 ``save_m2m()`` to save the many-to-many form data. For example::
289 
290     # Create a form instance with POST data.
291-    >>> a = Author()
292-    >>> f = AuthorForm(a, request.POST)
293+    >>> f = AuthorForm(request.POST)
294 
295     # Create, but don't save the new author instance.
296     >>> new_author = f.save(commit=False)
297@@ -222,8 +225,7 @@
298 For example::
299 
300     # Create a form instance with POST data.
301-    >>> a = Author()
302-    >>> f = AuthorForm(a, request.POST)
303+    >>> f = AuthorForm(request.POST)
304 
305     # Create and save the new author instance. There's no need to do anything else.
306     >>> new_author = f.save()
307@@ -277,7 +279,7 @@
308     manually set anyextra required fields::
309     
310         instance = Instance(required_field='value')
311-        form = InstanceForm(instance, request.POST)
312+        form = InstanceForm(request.POST, instance=instance)
313         new_instance = form.save()
314 
315         instance = form.save(commit=False)