Django

Code

Ticket #6162: modelform-init-2.diff

File modelform-init-2.diff, 17.2 kB (added by ubernostrum, 10 months ago)

Updated patch

  • django/newforms/models.py

    old new  
    262262        return type.__new__(cls, name, bases, attrs) 
    263263 
    264264class 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): 
    268267        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) 
    270276        # if initial was provided, it should override the values from instance 
    271277        if initial is not None: 
    272278            object_data.update(initial) 
  • tests/modeltests/model_forms/models.py

    old new  
    2929    def __unicode__(self): 
    3030        return self.name 
    3131 
     32class 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 
    3239class Article(models.Model): 
    3340    headline = models.CharField(max_length=50) 
    3441    slug = models.SlugField() 
     
    155162... 
    156163ImproperlyConfigured: BadForm's base classes define more than one model. 
    157164 
     165Require either a model bound in Meta or an instance passed in on __init__(). 
    158166 
    159 # Old form_for_x tests ####################################################### 
     167>>> class NoModelForm(ModelForm): 
     168...     pass 
    160169 
     170>>> f = NoModelForm() 
     171Traceback (most recent call last): 
     172... 
     173ImproperlyConfigured: ModelForm must either be bound to a model class or receive a model instance in __init__() 
     174 
     175# Test valid ModelForms ####################################################### 
     176 
    161177>>> from django.newforms import ModelForm, CharField 
    162178>>> import datetime 
    163179 
     
    167183>>> class CategoryForm(ModelForm): 
    168184...     class Meta: 
    169185...         model = Category 
    170 >>> f = CategoryForm(Category()
     186>>> f = CategoryForm(
    171187>>> print f 
    172188<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr> 
    173189<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr> 
     
    179195>>> print f['name'] 
    180196<input id="id_name" type="text" name="name" maxlength="20" /> 
    181197 
    182 >>> f = CategoryForm(Category(), auto_id=False) 
     198>>> f = CategoryForm(auto_id=False) 
    183199>>> print f.as_ul() 
    184200<li>Name: <input type="text" name="name" maxlength="20" /></li> 
    185201<li>Slug: <input type="text" name="slug" maxlength="20" /></li> 
    186202<li>The URL: <input type="text" name="url" maxlength="40" /></li> 
    187203 
    188 >>> f = CategoryForm(Category(), {'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'}) 
     204>>> f = CategoryForm({'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'}) 
    189205>>> f.is_valid() 
    190206True 
    191207>>> f.cleaned_data 
     
    196212>>> Category.objects.all() 
    197213[<Category: Entertainment>] 
    198214 
    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'}) 
    200216>>> f.is_valid() 
    201217True 
    202218>>> f.cleaned_data 
     
    210226If you call save() with commit=False, then it will return an object that 
    211227hasn't yet been saved to the database. In this case, it's up to you to call 
    212228save() 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'}) 
    214230>>> f.is_valid() 
    215231True 
    216232>>> f.cleaned_data 
     
    225241[<Category: Entertainment>, <Category: It's a test>, <Category: Third test>] 
    226242 
    227243If 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'}) 
    229245>>> f.errors 
    230246{'name': [u'This field is required.'], 'slug': [u'This field is required.']} 
    231247>>> f.cleaned_data 
     
    236252Traceback (most recent call last): 
    237253... 
    238254ValueError: 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'}) 
    240256>>> f.save() 
    241257Traceback (most recent call last): 
    242258... 
     
    253269>>> class ArticleForm(ModelForm): 
    254270...     class Meta: 
    255271...         model = Article 
    256 >>> f = ArticleForm(Article(), auto_id=False) 
     272>>> f = ArticleForm(auto_id=False) 
    257273>>> print f 
    258274<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr> 
    259275<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr> 
     
    286302...     class Meta: 
    287303...         model = Article 
    288304...         fields = ('headline','pub_date') 
    289 >>> f = PartialArticleForm(Article(), auto_id=False) 
     305>>> f = PartialArticleForm(auto_id=False) 
    290306>>> print f 
    291307<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr> 
    292308<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr> 
    293309 
    294 Use form_for_instance to create a Form from a model instance. The differenc
    295 between this Form and one created via form_for_model is that the object's 
     310Pass the "instance" keyword argument to create a Form from a model instance. Th
     311difference between this Form and one created wthout the"instance" argument is that the object's 
    296312current values are inserted as 'initial' data in each Field. 
    297313>>> w = Writer.objects.get(name='Mike Royko') 
    298314>>> class RoykoForm(ModelForm): 
    299315...     class Meta: 
    300316...         model = Writer 
    301 >>> f = RoykoForm(w, auto_id=False
     317>>> f = RoykoForm(auto_id=False, instance=w
    302318>>> print f 
    303319<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr> 
    304320 
     
    309325>>> class TestArticleForm(ModelForm): 
    310326...     class Meta: 
    311327...         model = Article 
    312 >>> f = TestArticleForm(art, auto_id=False) 
     328>>> f = TestArticleForm(instance=art, auto_id=False) 
    313329>>> print f.as_ul() 
    314330<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li> 
    315331<li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li> 
     
    331347<option value="2">It&#39;s a test</option> 
    332348<option value="3">Third test</option> 
    333349</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
    335351>>> f.is_valid() 
    336352True 
    337353>>> test_art = f.save() 
     
    347363...     class Meta: 
    348364...         model = Article 
    349365...         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
    351367>>> print f.as_ul() 
    352368<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> 
    353369<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li> 
     
    370386>>> class TestArticleForm(ModelForm): 
    371387...     class Meta: 
    372388...         model = Article 
    373 >>> f = TestArticleForm(new_art, auto_id=False
     389>>> f = TestArticleForm(auto_id=False, instance=new_art
    374390>>> print f.as_ul() 
    375391<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> 
    376392<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li> 
     
    393409<option value="3">Third test</option> 
    394410</select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li> 
    395411 
    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
    398414>>> new_art = f.save() 
    399415>>> new_art.id 
    4004161 
     
    403419[<Category: Entertainment>, <Category: It's a test>] 
    404420 
    405421Now, 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
    408424>>> new_art = f.save() 
    409425>>> new_art.id 
    4104261 
     
    416432>>> class ArticleForm(ModelForm): 
    417433...     class Meta: 
    418434...         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', 
    420436...     'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']}) 
    421437>>> new_art = f.save() 
    422438>>> new_art.id 
     
    429445>>> class ArticleForm(ModelForm): 
    430446...     class Meta: 
    431447...         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', 
    433449...     'writer': u'1', 'article': u'Test.'}) 
    434450>>> new_art = f.save() 
    435451>>> new_art.id 
     
    443459>>> class ArticleForm(ModelForm): 
    444460...     class Meta: 
    445461...         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', 
    447463...     'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']}) 
    448464>>> new_art = f.save(commit=False) 
    449465 
     
    474490<Category: Third test> 
    475491>>> cat.id 
    4764923 
    477 >>> form = ShortCategory(cat, {'name': 'Third', 'slug': 'third', 'url': '3rd'}
     493>>> form = ShortCategory({'name': 'Third', 'slug': 'third', 'url': '3rd'}, instance=cat
    478494>>> form.save() 
    479495<Category: Third> 
    480496>>> Category.objects.get(id=3) 
     
    486502>>> class ArticleForm(ModelForm): 
    487503...     class Meta: 
    488504...         model = Article 
    489 >>> f = ArticleForm(Article(), auto_id=False) 
     505>>> f = ArticleForm(auto_id=False) 
    490506>>> print f.as_ul() 
    491507<li>Headline: <input type="text" name="headline" maxlength="50" /></li> 
    492508<li>Slug: <input type="text" name="slug" maxlength="50" /></li> 
     
    536552<option value="4">Fourth</option> 
    537553</select>  Hold down "Control", or "Command" on a Mac, to select more than one.</li> 
    538554 
     555By not binding the form to a specific model, and by explicitly 
     556specifying a list of fields, it's possible to use a ModelForm with any 
     557model which has fields of those names. Doing so requires that an 
     558instance 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 
    539572# ModelChoiceField ############################################################ 
    540573 
    541574>>> from django.newforms import ModelChoiceField, ModelMultipleChoiceField 
     
    690723>>> class PhoneNumberForm(ModelForm): 
    691724...     class Meta: 
    692725...         model = PhoneNumber 
    693 >>> f = PhoneNumberForm(PhoneNumber(), {'phone': '(312) 555-1212', 'description': 'Assistance'}) 
     726>>> f = PhoneNumberForm({'phone': '(312) 555-1212', 'description': 'Assistance'}) 
    694727>>> f.is_valid() 
    695728True 
    696729>>> f.cleaned_data 
  • docs/modelforms.txt

    old new  
    2424    ...         model = Article 
    2525 
    2626    # Creating a form to add an article. 
    27     >>> article = Article() 
    28     >>> form = ArticleForm(article) 
     27    >>> form = ArticleForm() 
    2928 
    3029    # Creating a form to change an existing article. 
    3130    >>> article = Article.objects.get(pk=1) 
    32     >>> form = ArticleForm(article) 
     31    >>> form = ArticleForm(instance=article) 
    3332 
    3433Field types 
    3534----------- 
     
    166165The ``save()`` method 
    167166--------------------- 
    168167 
    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:: 
     168Every form produced by ``ModelForm`` also has a ``save()`` 
     169method. This method creates and saves a database object from the data 
     170bound to the form. A subclass of ``ModelForm`` can accept an existing 
     171model instance as the keyword argument ``instance``; if this is 
     172supplied, ``save()`` will update that instance. If it's not supplied, 
     173``save()`` will create a new instance of the specified model:: 
    173174 
    174175    # Create a form instance from POST data. 
    175     >>> a = Article() 
    176     >>> f = ArticleForm(a, request.POST) 
     176    >>> f = ArticleForm(request.POST) 
    177177 
    178178    # Save a new Article object from the form's data. 
    179179    >>> new_article = f.save() 
    180180 
     181    # Create a form to edit an existing Article. 
     182    >>> a = Article.objects.get(pk=1) 
     183    >>> f = ArticleForm(instance=a) 
     184 
    181185Note that ``save()`` will raise a ``ValueError`` if the data in the form 
    182186doesn't validate -- i.e., ``if form.errors``. 
    183187 
     
    201205``save_m2m()`` to save the many-to-many form data. For example:: 
    202206 
    203207    # Create a form instance with POST data. 
    204     >>> a = Author() 
    205     >>> f = AuthorForm(a, request.POST) 
     208    >>> f = AuthorForm(request.POST) 
    206209 
    207210    # Create, but don't save the new author instance. 
    208211    >>> new_author = f.save(commit=False) 
     
    222225For example:: 
    223226 
    224227    # Create a form instance with POST data. 
    225     >>> a = Author() 
    226     >>> f = AuthorForm(a, request.POST) 
     228    >>> f = AuthorForm(request.POST) 
    227229 
    228230    # Create and save the new author instance. There's no need to do anything else. 
    229231    >>> new_author = f.save() 
     
    277279    manually set anyextra required fields:: 
    278280     
    279281        instance = Instance(required_field='value') 
    280         form = InstanceForm(instance, request.POST
     282        form = InstanceForm(request.POST, instance=instance
    281283        new_instance = form.save() 
    282284 
    283285        instance = form.save(commit=False) 
     
    289291 
    290292.. _section on saving forms: `The save() method`_ 
    291293 
     294Using a form with any of multiple models 
     295---------------------------------------- 
     296 
     297If you have several models which share a common set of fields, and 
     298want to expose just those fields for editing, you can define a 
     299``ModelForm`` subclass *without* specifying the model, and list only 
     300the shared fields to be displayed. 
     301 
     302For example, if your application has multiple models which represent 
     303different types of people, each with a "name" field, you could define 
     304a ``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 
     311You could then pass any instance of any model which has a "name" field 
     312as the ``instance`` keyword argument when creating an instance of the 
     313form. 
     314 
     315Note that when a ``ModelForm`` is used like this, two important 
     316restrictions apply: 
     317 
     3181. Only the fields which are explicitly declared on the form will be 
     319   displayed. 
     320 
     3212. 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         
     327Defining a ``ModelForm`` subclass without specifying a model, and then 
     328attempting to instantiate it without passing a model instance as the 
     329``instance`` keyword argument, is an error. 
     330 
     331 
    292332Overriding the default field types 
    293333---------------------------------- 
    294334