1
0
mirror of https://github.com/django/django.git synced 2025-10-24 06:06:09 +00:00

[4.2.x] Refs #34140 -- Applied rst code-block to non-Python examples.

Thanks to J.V. Zammit, Paolo Melchiorre, and Mariusz Felisiak for
reviews.

Backport of 534ac48297 from main.
This commit is contained in:
Carlton Gibson
2023-02-09 16:48:46 +01:00
committed by Mariusz Felisiak
parent 4a89aa25c9
commit b784768eef
120 changed files with 3998 additions and 1397 deletions

View File

@@ -8,7 +8,9 @@ Formsets
A formset is a layer of abstraction to work with multiple forms on the same
page. It can be best compared to a data grid. Let's say you have the following
form::
form:
.. code-block:: pycon
>>> from django import forms
>>> class ArticleForm(forms.Form):
@@ -16,14 +18,18 @@ form::
... pub_date = forms.DateField()
You might want to allow the user to create several articles at once. To create
a formset out of an ``ArticleForm`` you would do::
a formset out of an ``ArticleForm`` you would do:
.. code-block:: pycon
>>> from django.forms import formset_factory
>>> ArticleFormSet = formset_factory(ArticleForm)
You now have created a formset class named ``ArticleFormSet``.
Instantiating the formset gives you the ability to iterate over the forms
in the formset and display them as you would with a regular form::
in the formset and display them as you would with a regular form:
.. code-block:: pycon
>>> formset = ArticleFormSet()
>>> for form in formset:
@@ -34,7 +40,9 @@ in the formset and display them as you would with a regular form::
As you can see it only displayed one empty form. The number of empty forms
that is displayed is controlled by the ``extra`` parameter. By default,
:func:`~django.forms.formsets.formset_factory` defines one extra form; the
following example will create a formset class to display two blank forms::
following example will create a formset class to display two blank forms:
.. code-block:: pycon
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
@@ -55,7 +63,9 @@ Initial data is what drives the main usability of a formset. As shown above
you can define the number of extra forms. What this means is that you are
telling the formset how many additional forms to show in addition to the
number of forms it generates from the initial data. Let's take a look at an
example::
example:
.. code-block:: pycon
>>> import datetime
>>> from django.forms import formset_factory
@@ -94,7 +104,9 @@ Limiting the maximum number of forms
====================================
The ``max_num`` parameter to :func:`~django.forms.formsets.formset_factory`
gives you the ability to limit the number of forms the formset will display::
gives you the ability to limit the number of forms the formset will display:
.. code-block:: pycon
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
@@ -133,7 +145,9 @@ Limiting the maximum number of instantiated forms
The ``absolute_max`` parameter to :func:`.formset_factory` allows limiting the
number of forms that can be instantiated when supplying ``POST`` data. This
protects against memory exhaustion attacks using forged ``POST`` requests::
protects against memory exhaustion attacks using forged ``POST`` requests:
.. code-block:: pycon
>>> from django.forms.formsets import formset_factory
>>> from myapp.forms import ArticleForm
@@ -160,7 +174,9 @@ Formset validation
Validation with a formset is almost identical to a regular ``Form``. There is
an ``is_valid`` method on the formset to provide a convenient way to validate
all forms in the formset::
all forms in the formset:
.. code-block:: pycon
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
@@ -175,7 +191,9 @@ all forms in the formset::
We passed in no data to the formset which is resulting in a valid form. The
formset is smart enough to ignore extra forms that were not changed. If we
provide an invalid article::
provide an invalid article:
.. code-block:: pycon
>>> data = {
... 'form-TOTAL_FORMS': '2',
@@ -203,7 +221,9 @@ validation may be incorrect when adding and deleting forms.
.. method:: BaseFormSet.total_error_count()
To check how many errors there are in the formset, we can use the
``total_error_count`` method::
``total_error_count`` method:
.. code-block:: pycon
>>> # Using the previous example
>>> formset.errors
@@ -214,7 +234,9 @@ To check how many errors there are in the formset, we can use the
1
We can also check if form data differs from the initial data (i.e. the form was
sent without any data)::
sent without any data):
.. code-block:: pycon
>>> data = {
... 'form-TOTAL_FORMS': '1',
@@ -235,7 +257,9 @@ You may have noticed the additional data (``form-TOTAL_FORMS``,
``form-INITIAL_FORMS``) that was required in the formset's data above. This
data is required for the ``ManagementForm``. This form is used by the formset
to manage the collection of forms contained in the formset. If you don't
provide this management data, the formset will be invalid::
provide this management data, the formset will be invalid:
.. code-block:: pycon
>>> data = {
... 'form-0-title': 'Test',
@@ -301,7 +325,9 @@ you want to override. Error message keys include ``'too_few_forms'``,
respectively.
For example, here is the default error message when the
management form is missing::
management form is missing:
.. code-block:: pycon
>>> formset = ArticleFormSet({})
>>> formset.is_valid()
@@ -309,7 +335,9 @@ management form is missing::
>>> formset.non_form_errors()
['ManagementForm data is missing or has been tampered with. Missing fields: form-TOTAL_FORMS, form-INITIAL_FORMS. You may need to file a bug report if the issue persists.']
And here is a custom error message::
And here is a custom error message:
.. code-block:: pycon
>>> formset = ArticleFormSet({}, error_messages={'missing_management_form': 'Sorry, something went wrong.'})
>>> formset.is_valid()
@@ -325,7 +353,9 @@ Custom formset validation
-------------------------
A formset has a ``clean`` method similar to the one on a ``Form`` class. This
is where you define your own validation that works at the formset level::
is where you define your own validation that works at the formset level:
.. code-block:: pycon
>>> from django.core.exceptions import ValidationError
>>> from django.forms import BaseFormSet
@@ -479,7 +509,9 @@ formsets and deletion of forms from a formset.
Default: ``False``
Lets you create a formset with the ability to order::
Lets you create a formset with the ability to order:
.. code-block:: pycon
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
@@ -503,7 +535,9 @@ Lets you create a formset with the ability to order::
This adds an additional field to each form. This new field is named ``ORDER``
and is an ``forms.IntegerField``. For the forms that came from the initial
data it automatically assigned them a numeric value. Let's look at what will
happen when the user changes these values::
happen when the user changes these values:
.. code-block:: pycon
>>> data = {
... 'form-TOTAL_FORMS': '3',
@@ -545,7 +579,9 @@ control the widget used with
Default: :class:`~django.forms.NumberInput`
Set ``ordering_widget`` to specify the widget class to be used with
``can_order``::
``can_order``:
.. code-block:: pycon
>>> from django.forms import BaseFormSet, formset_factory
>>> from myapp.forms import ArticleForm
@@ -560,7 +596,9 @@ Set ``ordering_widget`` to specify the widget class to be used with
.. method:: BaseFormSet.get_ordering_widget()
Override ``get_ordering_widget()`` if you need to provide a widget instance for
use with ``can_order``::
use with ``can_order``:
.. code-block:: pycon
>>> from django.forms import BaseFormSet, formset_factory
>>> from myapp.forms import ArticleForm
@@ -577,7 +615,9 @@ use with ``can_order``::
Default: ``False``
Lets you create a formset with the ability to select forms for deletion::
Lets you create a formset with the ability to select forms for deletion:
.. code-block:: pycon
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
@@ -600,7 +640,9 @@ Lets you create a formset with the ability to select forms for deletion::
Similar to ``can_order`` this adds a new field to each form named ``DELETE``
and is a ``forms.BooleanField``. When data comes through marking any of the
delete fields you can access them with ``deleted_forms``::
delete fields you can access them with ``deleted_forms``:
.. code-block:: pycon
>>> data = {
... 'form-TOTAL_FORMS': '3',
@@ -631,7 +673,9 @@ If you call ``formset.save(commit=False)``, objects will not be deleted
automatically. You'll need to call ``delete()`` on each of the
:attr:`formset.deleted_objects
<django.forms.models.BaseModelFormSet.deleted_objects>` to actually delete
them::
them:
.. code-block:: pycon
>>> instances = formset.save(commit=False)
>>> for obj in formset.deleted_objects:
@@ -655,7 +699,9 @@ control the widget used with
Default: :class:`~django.forms.CheckboxInput`
Set ``deletion_widget`` to specify the widget class to be used with
``can_delete``::
``can_delete``:
.. code-block:: pycon
>>> from django.forms import BaseFormSet, formset_factory
>>> from myapp.forms import ArticleForm
@@ -670,7 +716,9 @@ Set ``deletion_widget`` to specify the widget class to be used with
.. method:: BaseFormSet.get_deletion_widget()
Override ``get_deletion_widget()`` if you need to provide a widget instance for
use with ``can_delete``::
use with ``can_delete``:
.. code-block:: pycon
>>> from django.forms import BaseFormSet, formset_factory
>>> from myapp.forms import ArticleForm
@@ -696,7 +744,9 @@ Adding additional fields to a formset
If you need to add additional fields to the formset this can be easily
accomplished. The formset base class provides an ``add_fields`` method. You
can override this method to add your own fields or even redefine the default
fields/attributes of the order and deletion fields::
fields/attributes of the order and deletion fields:
.. code-block:: pycon
>>> from django.forms import BaseFormSet
>>> from django.forms import formset_factory
@@ -720,7 +770,9 @@ Passing custom parameters to formset forms
==========================================
Sometimes your form class takes custom parameters, like ``MyArticleForm``.
You can pass this parameter when instantiating the formset::
You can pass this parameter when instantiating the formset:
.. code-block:: pycon
>>> from django.forms import BaseFormSet
>>> from django.forms import formset_factory
@@ -737,7 +789,9 @@ You can pass this parameter when instantiating the formset::
The ``form_kwargs`` may also depend on the specific form instance. The formset
base class provides a ``get_form_kwargs`` method. The method takes a single
argument - the index of the form in the formset. The index is ``None`` for the
:ref:`empty_form`::
:ref:`empty_form`:
.. code-block:: pycon
>>> from django.forms import BaseFormSet
>>> from django.forms import formset_factory

View File

@@ -748,7 +748,9 @@ Useful attributes on ``{{ field }}`` include:
``{{ field.label_tag }}``
The field's label wrapped in the appropriate HTML ``<label>`` tag. This
includes the form's :attr:`~django.forms.Form.label_suffix`. For example,
the default ``label_suffix`` is a colon::
the default ``label_suffix`` is a colon:
.. code-block:: html+django
<label for="id_email">Email address:</label>

View File

@@ -67,7 +67,9 @@ to include the CSS file ``pretty.css``, and the JavaScript files
This static definition is converted at runtime into a widget property
named ``media``. The list of assets for a ``CalendarWidget`` instance
can be retrieved through this property::
can be retrieved through this property:
.. code-block:: pycon
>>> w = CalendarWidget()
>>> print(w.media)
@@ -112,7 +114,9 @@ requirements::
'print': ['newspaper.css],
}
If this last CSS definition were to be rendered, it would become the following HTML::
If this last CSS definition were to be rendered, it would become the following HTML:
.. code-block:: html+django
<link href="http://static.example.com/pretty.css" media="screen" rel="stylesheet">
<link href="http://static.example.com/lo_res.css" media="tv,projector" rel="stylesheet">
@@ -139,7 +143,9 @@ By default, any object using a static ``Media`` definition will
inherit all the assets associated with the parent widget. This occurs
regardless of how the parent defines its own requirements. For
example, if we were to extend our basic Calendar widget from the
example above::
example above:
.. code-block:: pycon
>>> class FancyCalendarWidget(CalendarWidget):
... class Media:
@@ -158,7 +164,9 @@ example above::
The FancyCalendar widget inherits all the assets from its parent
widget. If you don't want ``Media`` to be inherited in this way, add
an ``extend=False`` declaration to the ``Media`` declaration::
an ``extend=False`` declaration to the ``Media`` declaration:
.. code-block:: pycon
>>> class FancyCalendarWidget(CalendarWidget):
... class Media:
@@ -224,7 +232,9 @@ To find the appropriate prefix to use, Django will check if the
:setting:`STATIC_URL` setting is not ``None`` and automatically fall back
to using :setting:`MEDIA_URL`. For example, if the :setting:`MEDIA_URL` for
your site was ``'http://uploads.example.com/'`` and :setting:`STATIC_URL`
was ``None``::
was ``None``:
.. code-block:: pycon
>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
@@ -240,7 +250,9 @@ was ``None``::
<script src="http://uploads.example.com/animations.js"></script>
<script src="http://othersite.com/actions.js"></script>
But if :setting:`STATIC_URL` is ``'http://static.example.com/'``::
But if :setting:`STATIC_URL` is ``'http://static.example.com/'``:
.. code-block:: pycon
>>> w = CalendarWidget()
>>> print(w.media)
@@ -249,7 +261,9 @@ But if :setting:`STATIC_URL` is ``'http://static.example.com/'``::
<script src="http://othersite.com/actions.js"></script>
Or if :mod:`~django.contrib.staticfiles` is configured using the
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage`::
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage`:
.. code-block:: pycon
>>> w = CalendarWidget()
>>> print(w.media)
@@ -265,7 +279,9 @@ Paths as objects
Asset paths may also be given as hashable objects implementing an
``__html__()`` method. The ``__html__()`` method is typically added using the
:func:`~django.utils.html.html_safe` decorator. The object is responsible for
outputting the complete HTML ``<script>`` or ``<link>`` tag content::
outputting the complete HTML ``<script>`` or ``<link>`` tag content:
.. code-block:: pycon
>>> from django import forms
>>> from django.utils.html import html_safe
@@ -294,7 +310,9 @@ Subsets of assets
-----------------
If you only want files of a particular type, you can use the subscript
operator to filter out a medium of interest. For example::
operator to filter out a medium of interest. For example:
.. code-block:: pycon
>>> w = CalendarWidget()
>>> print(w.media)
@@ -313,7 +331,9 @@ Combining ``Media`` objects
``Media`` objects can also be added together. When two ``Media`` objects are
added, the resulting ``Media`` object contains the union of the assets
specified by both::
specified by both:
.. code-block:: pycon
>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
@@ -345,7 +365,9 @@ example, you may have a script that depends on jQuery. Therefore, combining
``Media`` objects attempts to preserve the relative order in which assets are
defined in each ``Media`` class.
For example::
For example:
.. code-block:: pycon
>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
@@ -377,7 +399,9 @@ are exactly the same.
Regardless of whether you define a ``media`` declaration, *all* Form
objects have a ``media`` property. The default value for this property
is the result of adding the ``media`` definitions for all widgets that
are part of the form::
are part of the form:
.. code-block:: pycon
>>> from django import forms
>>> class ContactForm(forms.Form):
@@ -392,7 +416,9 @@ are part of the form::
<script src="http://static.example.com/whizbang.js"></script>
If you want to associate additional assets with a form -- for example,
CSS for form layout -- add a ``Media`` declaration to the form::
CSS for form layout -- add a ``Media`` declaration to the form:
.. code-block:: pycon
>>> class ContactForm(forms.Form):
... date = DateField(widget=CalendarWidget)

View File

@@ -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'))
@@ -998,7 +1038,9 @@ Preventing new objects creation
.. versionadded:: 4.1
Using the ``edit_only`` parameter, you can prevent creation of any new
objects::
objects:
.. code-block:: pycon
>>> AuthorFormSet = modelformset_factory(
... Author,
@@ -1106,18 +1148,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 }}
@@ -1130,7 +1174,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 }}
@@ -1143,7 +1189,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 }}
@@ -1161,8 +1209,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
@@ -1184,7 +1230,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'])
@@ -1227,7 +1275,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'],
@@ -1256,7 +1306,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'])