diff options
| author | Carlton Gibson <carlton.gibson@noumenal.es> | 2023-02-09 16:48:46 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-02-10 19:19:13 +0100 |
| commit | 534ac4829764f317cf2fbc4a18354fcc998c1425 (patch) | |
| tree | c85c1df220ea6c3a87f9820106ba5a06e9ec9394 /docs/topics/forms/modelforms.txt | |
| parent | 7bb741d787ba360a9f0d490db92e22e0d28204ed (diff) | |
Refs #34140 -- Applied rst code-block to non-Python examples.
Thanks to J.V. Zammit, Paolo Melchiorre, and Mariusz Felisiak for
reviews.
Diffstat (limited to 'docs/topics/forms/modelforms.txt')
| -rw-r--r-- | docs/topics/forms/modelforms.txt | 116 |
1 files changed, 84 insertions, 32 deletions
diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt index 253a4a01a4..4242cd96e0 100644 --- a/docs/topics/forms/modelforms.txt +++ b/docs/topics/forms/modelforms.txt @@ -17,7 +17,9 @@ you've already defined the fields in your model. For this reason, Django provides a helper class that lets you create a ``Form`` class from a Django model. -For example:: +For example: + +.. code-block:: pycon >>> from django.forms import ModelForm >>> from myapp.models import Article @@ -320,7 +322,9 @@ Every ``ModelForm`` also has a ``save()`` method. This method creates and saves a database object from the data bound to the form. A subclass of ``ModelForm`` can accept an existing model instance as the keyword argument ``instance``; if this is supplied, ``save()`` will update that instance. If it's not supplied, -``save()`` will create a new instance of the specified model:: +``save()`` will create a new instance of the specified model: + +.. code-block:: pycon >>> from myapp.models import Article >>> from myapp.forms import ArticleForm @@ -373,7 +377,9 @@ exists in the database. To work around this problem, every time you save a form using ``commit=False``, Django adds a ``save_m2m()`` method to your ``ModelForm`` subclass. After you've manually saved the instance produced by the form, you can invoke -``save_m2m()`` to save the many-to-many form data. For example:: +``save_m2m()`` to save the many-to-many form data. For example: + +.. code-block:: pycon # Create a form instance with POST data. >>> f = AuthorForm(request.POST) @@ -392,7 +398,9 @@ you've manually saved the instance produced by the form, you can invoke Calling ``save_m2m()`` is only required if you use ``save(commit=False)``. When you use a ``save()`` on a form, all data -- including many-to-many data -- -is saved without the need for any additional method calls. For example:: +is saved without the need for any additional method calls. For example: + +.. code-block:: pycon # Create a form instance with POST data. >>> a = Author() @@ -680,7 +688,9 @@ Form inheritance As with basic forms, you can extend and reuse ``ModelForms`` by inheriting them. This is useful if you need to declare extra fields or extra methods on a parent class for use in a number of forms derived from models. For example, -using the previous ``ArticleForm`` class:: +using the previous ``ArticleForm`` class: + +.. code-block:: pycon >>> class EnhancedArticleForm(ArticleForm): ... def clean_pub_date(self): @@ -690,7 +700,9 @@ This creates a form that behaves identically to ``ArticleForm``, except there's some extra validation and cleaning for the ``pub_date`` field. You can also subclass the parent's ``Meta`` inner class if you want to change -the ``Meta.fields`` or ``Meta.exclude`` lists:: +the ``Meta.fields`` or ``Meta.exclude`` lists: + +.. code-block:: pycon >>> class RestrictedArticleForm(EnhancedArticleForm): ... class Meta(ArticleForm.Meta): @@ -725,7 +737,9 @@ Providing initial values As with regular forms, it's possible to specify initial data for forms by specifying an ``initial`` parameter when instantiating the form. Initial values provided this way will override both initial values from the form field -and values from an attached model instance. For example:: +and values from an attached model instance. For example: + +.. code-block:: pycon >>> article = Article.objects.get(pk=1) >>> article.headline @@ -742,14 +756,18 @@ ModelForm factory function You can create forms from a given model using the standalone function :func:`~django.forms.models.modelform_factory`, instead of using a class definition. This may be more convenient if you do not have many customizations -to make:: +to make: + +.. code-block:: pycon >>> from django.forms import modelform_factory >>> from myapp.models import Book >>> BookForm = modelform_factory(Book, fields=["author", "title"]) This can also be used to make modifications to existing forms, for example by -specifying the widgets to be used for a given field:: +specifying the widgets to be used for a given field: + +.. code-block:: pycon >>> from django.forms import Textarea >>> Form = modelform_factory(Book, form=BookForm, @@ -773,7 +791,9 @@ Model formsets Like :doc:`regular formsets </topics/forms/formsets>`, Django provides a couple of enhanced formset classes to make working with Django models more -convenient. Let's reuse the ``Author`` model from above:: +convenient. Let's reuse the ``Author`` model from above: + +.. code-block:: pycon >>> from django.forms import modelformset_factory >>> from myapp.models import Author @@ -781,12 +801,16 @@ convenient. Let's reuse the ``Author`` model from above:: Using ``fields`` restricts the formset to use only the given fields. Alternatively, you can take an "opt-out" approach, specifying which fields to -exclude:: +exclude: + +.. code-block:: pycon >>> AuthorFormSet = modelformset_factory(Author, exclude=['birth_date']) This will create a formset that is capable of working with the data associated -with the ``Author`` model. It works just like a regular formset:: +with the ``Author`` model. It works just like a regular formset: + +.. code-block:: pycon >>> formset = AuthorFormSet() >>> print(formset) @@ -818,7 +842,9 @@ Changing the queryset By default, when you create a formset from a model, the formset will use a queryset that includes all objects in the model (e.g., ``Author.objects.all()``). You can override this behavior by using the -``queryset`` argument:: +``queryset`` argument: + +.. code-block:: pycon >>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O')) @@ -833,13 +859,17 @@ Alternatively, you can create a subclass that sets ``self.queryset`` in super().__init__(*args, **kwargs) self.queryset = Author.objects.filter(name__startswith='O') -Then, pass your ``BaseAuthorFormSet`` class to the factory function:: +Then, pass your ``BaseAuthorFormSet`` class to the factory function: + +.. code-block:: pycon >>> AuthorFormSet = modelformset_factory( ... Author, fields=['name', 'title'], formset=BaseAuthorFormSet) If you want to return a formset that doesn't include *any* preexisting -instances of the model, you can specify an empty QuerySet:: +instances of the model, you can specify an empty QuerySet: + +.. code-block:: pycon >>> AuthorFormSet(queryset=Author.objects.none()) @@ -874,7 +904,9 @@ Specifying widgets to use in the form with ``widgets`` Using the ``widgets`` parameter, you can specify a dictionary of values to customize the ``ModelForm``’s widget class for a particular field. This works the same way as the ``widgets`` dictionary on the inner ``Meta`` -class of a ``ModelForm`` works:: +class of a ``ModelForm`` works: + +.. code-block:: pycon >>> AuthorFormSet = modelformset_factory( ... Author, fields=['name', 'title'], @@ -912,7 +944,9 @@ Saving objects in the formset ----------------------------- As with a ``ModelForm``, you can save the data as a model object. This is done -with the formset's ``save()`` method:: +with the formset's ``save()`` method: + +.. code-block:: pycon # Create a formset instance with POST data. >>> formset = AuthorFormSet(request.POST) @@ -930,7 +964,9 @@ excluded), these fields will not be set by the ``save()`` method. You can find more information about this restriction, which also holds for regular ``ModelForms``, in `Selecting the fields to use`_. -Pass ``commit=False`` to return the unsaved model instances:: +Pass ``commit=False`` to return the unsaved model instances: + +.. code-block:: pycon # don't save to the database >>> instances = formset.save(commit=False) @@ -959,7 +995,9 @@ As with regular formsets, you can use the ``max_num`` and ``extra`` parameters to :func:`~django.forms.models.modelformset_factory` to limit the number of extra forms displayed. -``max_num`` does not prevent existing objects from being displayed:: +``max_num`` does not prevent existing objects from being displayed: + +.. code-block:: pycon >>> Author.objects.order_by('name') <QuerySet [<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>]> @@ -976,7 +1014,9 @@ this. If the value of ``max_num`` is greater than the number of existing related objects, up to ``extra`` additional blank forms will be added to the formset, -so long as the total number of forms does not exceed ``max_num``:: +so long as the total number of forms does not exceed ``max_num``: + +.. code-block:: pycon >>> AuthorFormSet = modelformset_factory(Author, fields=['name'], max_num=4, extra=2) >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name')) @@ -996,7 +1036,9 @@ Preventing new objects creation ------------------------------- Using the ``edit_only`` parameter, you can prevent creation of any new -objects:: +objects: + +.. code-block:: pycon >>> AuthorFormSet = modelformset_factory( ... Author, @@ -1104,18 +1146,20 @@ cases in this example. Using the formset in the template --------------------------------- -.. highlight:: html+django - There are three ways to render a formset in a Django template. -First, you can let the formset do most of the work:: +First, you can let the formset do most of the work: + +.. code-block:: html+django <form method="post"> {{ formset }} </form> Second, you can manually render the formset, but let the form deal with -itself:: +itself: + +.. code-block:: html+django <form method="post"> {{ formset.management_form }} @@ -1128,7 +1172,9 @@ When you manually render the forms yourself, be sure to render the management form as shown above. See the :ref:`management form documentation <understanding-the-managementform>`. -Third, you can manually render each field:: +Third, you can manually render each field: + +.. code-block:: html+django <form method="post"> {{ formset.management_form }} @@ -1141,7 +1187,9 @@ Third, you can manually render each field:: If you opt to use this third method and you don't iterate over the fields with a ``{% for %}`` loop, you'll need to render the primary key field. For example, -if you were rendering the ``name`` and ``age`` fields of a model:: +if you were rendering the ``name`` and ``age`` fields of a model: + +.. code-block:: html+django <form method="post"> {{ formset.management_form }} @@ -1159,8 +1207,6 @@ the model formset, in the ``POST`` case, will work correctly. (This example assumes a primary key named ``id``. If you've explicitly defined your own primary key that isn't called ``id``, make sure it gets rendered.) -.. highlight:: python - .. _inline-formsets: Inline formsets @@ -1182,7 +1228,9 @@ you have these two models:: title = models.CharField(max_length=100) If you want to create a formset that allows you to edit books belonging to -a particular author, you could do this:: +a particular author, you could do this: + +.. code-block:: pycon >>> from django.forms import inlineformset_factory >>> BookFormSet = inlineformset_factory(Author, Book, fields=['title']) @@ -1225,7 +1273,9 @@ For example, if you want to override ``clean()``:: See also :ref:`model-formsets-overriding-clean`. Then when you create your inline formset, pass in the optional argument -``formset``:: +``formset``: + +.. code-block:: pycon >>> from django.forms import inlineformset_factory >>> BookFormSet = inlineformset_factory(Author, Book, fields=['title'], @@ -1254,7 +1304,9 @@ the following model:: length_in_months = models.IntegerField() To resolve this, you can use ``fk_name`` to -:func:`~django.forms.models.inlineformset_factory`:: +:func:`~django.forms.models.inlineformset_factory`: + +.. code-block:: pycon >>> FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name='from_friend', ... fields=['to_friend', 'length_in_months']) |
