Ticket #6162: modelform-init-2.diff
File modelform-init-2.diff, 17.2 KB (added by , 17 years ago) |
---|
-
django/newforms/models.py
262 262 return type.__new__(cls, name, bases, attrs) 263 263 264 264 class BaseModelForm(BaseForm): 265 def __init__(self, instance, data=None, files=None, auto_id='id_%s', prefix=None, 266 initial=None, error_class=ErrorList, label_suffix=':'): 267 self.instance = instance 265 def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, 266 initial=None, error_class=ErrorList, label_suffix=':', instance=None): 268 267 opts = self._meta 269 object_data = model_to_dict(instance, opts.fields, opts.exclude) 268 if instance is None and opts.model is None: 269 raise ImproperlyConfigured("ModelForm must either be bound to a model class or receive a model instance in __init__()") 270 if instance is None: 271 self.instance = opts.model() 272 object_data = {} 273 else: 274 self.instance = instance 275 object_data = model_to_dict(instance, opts.fields, opts.exclude) 270 276 # if initial was provided, it should override the values from instance 271 277 if initial is not None: 272 278 object_data.update(initial) -
tests/modeltests/model_forms/models.py
29 29 def __unicode__(self): 30 30 return self.name 31 31 32 class Editor(models.Model): 33 name = models.CharField(max_length=50, help_text='Use both first and last names.') 34 categories = models.ManyToManyField(Category) 35 36 def __unicode__(self): 37 return self.name 38 32 39 class Article(models.Model): 33 40 headline = models.CharField(max_length=50) 34 41 slug = models.SlugField() … … 155 162 ... 156 163 ImproperlyConfigured: BadForm's base classes define more than one model. 157 164 165 Require either a model bound in Meta or an instance passed in on __init__(). 158 166 159 # Old form_for_x tests ####################################################### 167 >>> class NoModelForm(ModelForm): 168 ... pass 160 169 170 >>> f = NoModelForm() 171 Traceback (most recent call last): 172 ... 173 ImproperlyConfigured: ModelForm must either be bound to a model class or receive a model instance in __init__() 174 175 # Test valid ModelForms ####################################################### 176 161 177 >>> from django.newforms import ModelForm, CharField 162 178 >>> import datetime 163 179 … … 167 183 >>> class CategoryForm(ModelForm): 168 184 ... class Meta: 169 185 ... model = Category 170 >>> f = CategoryForm( Category())186 >>> f = CategoryForm() 171 187 >>> print f 172 188 <tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr> 173 189 <tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr> … … 179 195 >>> print f['name'] 180 196 <input id="id_name" type="text" name="name" maxlength="20" /> 181 197 182 >>> f = CategoryForm( Category(),auto_id=False)198 >>> f = CategoryForm(auto_id=False) 183 199 >>> print f.as_ul() 184 200 <li>Name: <input type="text" name="name" maxlength="20" /></li> 185 201 <li>Slug: <input type="text" name="slug" maxlength="20" /></li> 186 202 <li>The URL: <input type="text" name="url" maxlength="40" /></li> 187 203 188 >>> f = CategoryForm( Category(),{'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'})204 >>> f = CategoryForm({'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'}) 189 205 >>> f.is_valid() 190 206 True 191 207 >>> f.cleaned_data … … 196 212 >>> Category.objects.all() 197 213 [<Category: Entertainment>] 198 214 199 >>> f = CategoryForm( Category(),{'name': "It's a test", 'slug': 'its-test', 'url': 'test'})215 >>> f = CategoryForm({'name': "It's a test", 'slug': 'its-test', 'url': 'test'}) 200 216 >>> f.is_valid() 201 217 True 202 218 >>> f.cleaned_data … … 210 226 If you call save() with commit=False, then it will return an object that 211 227 hasn't yet been saved to the database. In this case, it's up to you to call 212 228 save() on the resulting model instance. 213 >>> f = CategoryForm( Category(),{'name': 'Third test', 'slug': 'third-test', 'url': 'third'})229 >>> f = CategoryForm({'name': 'Third test', 'slug': 'third-test', 'url': 'third'}) 214 230 >>> f.is_valid() 215 231 True 216 232 >>> f.cleaned_data … … 225 241 [<Category: Entertainment>, <Category: It's a test>, <Category: Third test>] 226 242 227 243 If you call save() with invalid data, you'll get a ValueError. 228 >>> f = CategoryForm( Category(),{'name': '', 'slug': '', 'url': 'foo'})244 >>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'}) 229 245 >>> f.errors 230 246 {'name': [u'This field is required.'], 'slug': [u'This field is required.']} 231 247 >>> f.cleaned_data … … 236 252 Traceback (most recent call last): 237 253 ... 238 254 ValueError: The Category could not be created because the data didn't validate. 239 >>> f = CategoryForm( Category(),{'name': '', 'slug': '', 'url': 'foo'})255 >>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'}) 240 256 >>> f.save() 241 257 Traceback (most recent call last): 242 258 ... … … 253 269 >>> class ArticleForm(ModelForm): 254 270 ... class Meta: 255 271 ... model = Article 256 >>> f = ArticleForm( Article(),auto_id=False)272 >>> f = ArticleForm(auto_id=False) 257 273 >>> print f 258 274 <tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr> 259 275 <tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr> … … 286 302 ... class Meta: 287 303 ... model = Article 288 304 ... fields = ('headline','pub_date') 289 >>> f = PartialArticleForm( Article(),auto_id=False)305 >>> f = PartialArticleForm(auto_id=False) 290 306 >>> print f 291 307 <tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr> 292 308 <tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr> 293 309 294 Use form_for_instance to create a Form from a model instance. The difference295 between this Form and one created via form_for_modelis that the object's310 Pass the "instance" keyword argument to create a Form from a model instance. The 311 difference between this Form and one created wthout the"instance" argument is that the object's 296 312 current values are inserted as 'initial' data in each Field. 297 313 >>> w = Writer.objects.get(name='Mike Royko') 298 314 >>> class RoykoForm(ModelForm): 299 315 ... class Meta: 300 316 ... model = Writer 301 >>> f = RoykoForm( w, auto_id=False)317 >>> f = RoykoForm(auto_id=False, instance=w) 302 318 >>> print f 303 319 <tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr> 304 320 … … 309 325 >>> class TestArticleForm(ModelForm): 310 326 ... class Meta: 311 327 ... model = Article 312 >>> f = TestArticleForm( art, auto_id=False)328 >>> f = TestArticleForm(instance=art, auto_id=False) 313 329 >>> print f.as_ul() 314 330 <li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li> 315 331 <li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li> … … 331 347 <option value="2">It's a test</option> 332 348 <option value="3">Third test</option> 333 349 </select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> 334 >>> f = TestArticleForm( art, {'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'})350 >>> f = TestArticleForm({'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'}, instance=art) 335 351 >>> f.is_valid() 336 352 True 337 353 >>> test_art = f.save() … … 347 363 ... class Meta: 348 364 ... model = Article 349 365 ... fields=('headline', 'slug', 'pub_date') 350 >>> f = PartialArticleForm( art, {'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False)366 >>> f = PartialArticleForm({'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False, instance=art) 351 367 >>> print f.as_ul() 352 368 <li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> 353 369 <li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li> … … 370 386 >>> class TestArticleForm(ModelForm): 371 387 ... class Meta: 372 388 ... model = Article 373 >>> f = TestArticleForm( new_art, auto_id=False)389 >>> f = TestArticleForm(auto_id=False, instance=new_art) 374 390 >>> print f.as_ul() 375 391 <li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> 376 392 <li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li> … … 393 409 <option value="3">Third test</option> 394 410 </select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> 395 411 396 >>> f = TestArticleForm( new_art,{'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',397 ... 'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']} )412 >>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04', 413 ... 'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']}, instance=new_art) 398 414 >>> new_art = f.save() 399 415 >>> new_art.id 400 416 1 … … 403 419 [<Category: Entertainment>, <Category: It's a test>] 404 420 405 421 Now, submit form data with no categories. This deletes the existing categories. 406 >>> f = TestArticleForm( new_art,{'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04',407 ... 'writer': u'1', 'article': u'Hello.'} )422 >>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04', 423 ... 'writer': u'1', 'article': u'Hello.'}, instance=new_art) 408 424 >>> new_art = f.save() 409 425 >>> new_art.id 410 426 1 … … 416 432 >>> class ArticleForm(ModelForm): 417 433 ... class Meta: 418 434 ... model = Article 419 >>> f = ArticleForm( Article(),{'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',435 >>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01', 420 436 ... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']}) 421 437 >>> new_art = f.save() 422 438 >>> new_art.id … … 429 445 >>> class ArticleForm(ModelForm): 430 446 ... class Meta: 431 447 ... model = Article 432 >>> f = ArticleForm( Article(),{'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01',448 >>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01', 433 449 ... 'writer': u'1', 'article': u'Test.'}) 434 450 >>> new_art = f.save() 435 451 >>> new_art.id … … 443 459 >>> class ArticleForm(ModelForm): 444 460 ... class Meta: 445 461 ... model = Article 446 >>> f = ArticleForm( Article(),{'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01',462 >>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01', 447 463 ... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']}) 448 464 >>> new_art = f.save(commit=False) 449 465 … … 474 490 <Category: Third test> 475 491 >>> cat.id 476 492 3 477 >>> form = ShortCategory( cat, {'name': 'Third', 'slug': 'third', 'url': '3rd'})493 >>> form = ShortCategory({'name': 'Third', 'slug': 'third', 'url': '3rd'}, instance=cat) 478 494 >>> form.save() 479 495 <Category: Third> 480 496 >>> Category.objects.get(id=3) … … 486 502 >>> class ArticleForm(ModelForm): 487 503 ... class Meta: 488 504 ... model = Article 489 >>> f = ArticleForm( Article(),auto_id=False)505 >>> f = ArticleForm(auto_id=False) 490 506 >>> print f.as_ul() 491 507 <li>Headline: <input type="text" name="headline" maxlength="50" /></li> 492 508 <li>Slug: <input type="text" name="slug" maxlength="50" /></li> … … 536 552 <option value="4">Fourth</option> 537 553 </select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> 538 554 555 By not binding the form to a specific model, and by explicitly 556 specifying a list of fields, it's possible to use a ModelForm with any 557 model which has fields of those names. Doing so requires that an 558 instance be passed in on form instantiation. 559 560 >>> class WriterOrEditorForm(ModelForm): 561 ... name = forms.CharField(max_length=50) 562 >>> w = Writer() 563 >>> f = WriterOrEditorForm(instance=w) 564 >>> print f.as_ul() 565 <li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="50" /></li> 566 >>> e = Editor(name="Horace Greeley") 567 >>> f = WriterOrEditorForm(instance=e) 568 >>> print f.as_ul() 569 <li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" value="Horace Greeley" maxlength="50" /></li> 570 571 539 572 # ModelChoiceField ############################################################ 540 573 541 574 >>> from django.newforms import ModelChoiceField, ModelMultipleChoiceField … … 690 723 >>> class PhoneNumberForm(ModelForm): 691 724 ... class Meta: 692 725 ... model = PhoneNumber 693 >>> f = PhoneNumberForm( PhoneNumber(),{'phone': '(312) 555-1212', 'description': 'Assistance'})726 >>> f = PhoneNumberForm({'phone': '(312) 555-1212', 'description': 'Assistance'}) 694 727 >>> f.is_valid() 695 728 True 696 729 >>> f.cleaned_data -
docs/modelforms.txt
24 24 ... model = Article 25 25 26 26 # Creating a form to add an article. 27 >>> article = Article() 28 >>> form = ArticleForm(article) 27 >>> form = ArticleForm() 29 28 30 29 # Creating a form to change an existing article. 31 30 >>> article = Article.objects.get(pk=1) 32 >>> form = ArticleForm( article)31 >>> form = ArticleForm(instance=article) 33 32 34 33 Field types 35 34 ----------- … … 166 165 The ``save()`` method 167 166 --------------------- 168 167 169 Every form produced by ``ModelForm`` also has a ``save()`` method. This 170 method creates and saves a database object from the data bound to the form. 171 A subclass of ``ModelForm`` also requires a model instance as the first 172 arument to its constructor. For example:: 168 Every form produced by ``ModelForm`` also has a ``save()`` 169 method. This method creates and saves a database object from the data 170 bound to the form. A subclass of ``ModelForm`` can accept an existing 171 model instance as the keyword argument ``instance``; if this is 172 supplied, ``save()`` will update that instance. If it's not supplied, 173 ``save()`` will create a new instance of the specified model:: 173 174 174 175 # Create a form instance from POST data. 175 >>> a = Article() 176 >>> f = ArticleForm(a, request.POST) 176 >>> f = ArticleForm(request.POST) 177 177 178 178 # Save a new Article object from the form's data. 179 179 >>> new_article = f.save() 180 180 181 # Create a form to edit an existing Article. 182 >>> a = Article.objects.get(pk=1) 183 >>> f = ArticleForm(instance=a) 184 181 185 Note that ``save()`` will raise a ``ValueError`` if the data in the form 182 186 doesn't validate -- i.e., ``if form.errors``. 183 187 … … 201 205 ``save_m2m()`` to save the many-to-many form data. For example:: 202 206 203 207 # Create a form instance with POST data. 204 >>> a = Author() 205 >>> f = AuthorForm(a, request.POST) 208 >>> f = AuthorForm(request.POST) 206 209 207 210 # Create, but don't save the new author instance. 208 211 >>> new_author = f.save(commit=False) … … 222 225 For example:: 223 226 224 227 # Create a form instance with POST data. 225 >>> a = Author() 226 >>> f = AuthorForm(a, request.POST) 228 >>> f = AuthorForm(request.POST) 227 229 228 230 # Create and save the new author instance. There's no need to do anything else. 229 231 >>> new_author = f.save() … … 277 279 manually set anyextra required fields:: 278 280 279 281 instance = Instance(required_field='value') 280 form = InstanceForm( instance, request.POST)282 form = InstanceForm(request.POST, instance=instance) 281 283 new_instance = form.save() 282 284 283 285 instance = form.save(commit=False) … … 289 291 290 292 .. _section on saving forms: `The save() method`_ 291 293 294 Using a form with any of multiple models 295 ---------------------------------------- 296 297 If you have several models which share a common set of fields, and 298 want to expose just those fields for editing, you can define a 299 ``ModelForm`` subclass *without* specifying the model, and list only 300 the shared fields to be displayed. 301 302 For example, if your application has multiple models which represent 303 different types of people, each with a "name" field, you could define 304 a ``ModelForm`` subclass like so:: 305 306 from django import newforms as forms 307 308 class PersonNameForm(forms.ModelForm): 309 name = forms.CharField(max_length=50) 310 311 You could then pass any instance of any model which has a "name" field 312 as the ``instance`` keyword argument when creating an instance of the 313 form. 314 315 Note that when a ``ModelForm`` is used like this, two important 316 restrictions apply: 317 318 1. Only the fields which are explicitly declared on the form will be 319 displayed. 320 321 2. It is your responsibility to supply values for any other required 322 fields before saving the model instance, either by filling them in 323 on the instance before passing it to the form, or by using the 324 ``commit=False`` argument to ``save()`` and then filling in the 325 fields before actually saving the instance to the databae. 326 327 Defining a ``ModelForm`` subclass without specifying a model, and then 328 attempting to instantiate it without passing a model instance as the 329 ``instance`` keyword argument, is an error. 330 331 292 332 Overriding the default field types 293 333 ---------------------------------- 294 334