# documentação Django 3.1.9.dev

# Trabalhando com formulários

Sobre este documento

Este documento fornece uma introdução ao básico de formulários web e como eles são manipulados no Django. Para mais detalhes olhe nas áreas específica da API de formulários, veja The Forms API, Form fields, e Form and field validation.

A menos que você planeje construir websites e aplicações que não façam outra coisa além de publicar conteúdo, e não aceita entrada de seus visitantes, você irá precisar entender e usar formulários.

O Django fornece uma gama de ferramentas e bibliotecas para auxiliar a construção de formulários para entrada de dados vindos dos seus visitantes, e então os processa e responde àquela entrada.

## Formulários HTML

Em HTML, um formulário é uma coleção de elementos dentro de `<form>...</form>` que permitem que os visitantes façam coisas como escrever um texto, selecionar opções, manipular objetos ou controle e assim por diante, e então enviar esta informação de volta ao servidor.

Some of these form interface elements - text input or checkboxes - are built into HTML itself. Others are much more complex; an interface that pops up a date picker or allows you to move a slider or manipulate controls will typically use JavaScript and CSS as well as HTML form `<input>` elements to achieve these effects.

Assim como seus elementos `<input>`, um formulário precisa especificar duas coisas:

- onde: a URL para a qual o dado correspondente à entrada do usuário deve ser enviado.
- como: o método HTTP pelo qual o dado deve ser retornado

Como um exemplo, o formulário de autenticação do admin do Django contém vários elementos do tipo `<input>`: um `type="text"` para o nome do usuário, um de `type="password"` para a senha, e um `type="submit"` par ao botão “Log in”. Ele também contém alguns objetos escondidos do tipo texto que o usuário não vê, o qual o Django usa para determinar o que fazer depois.

Ele também dia ao navegador web que os dados do formulário devem ser enviados para a URL especificada no atributo `<action>` do `<form>` - `/admin/` - e isso deve ser enviado usando o mecanismo HTTP especificado pelo atributo `method` - `post`.

Quando o elemento `<input type="submit" value="Log in">` e disparado, os dados são retornados para `/admin/`.

### `GET` e `POST`

`GET` e `POST` são os únicos métodos HTTP a se usar enquanto lida com formulários.

O formulário de autenticação do Django é retornado usando o método `POST`, no qual o navegador web empacota os dados do formulário, codifica-os para transmissão, envia para o servidor, e então recebe de volta sua resposta.

O `GET`, em contraste, empacota os dados enviados em uma string, e usa isso para compor a URL. A URL contém o endereço para onde o dado deve ser enviado, bem como as chaves dos dados e valore. Você pode ver isso em ação se você fizer uma busca na documentação do Django, a qual irá produzir uma URL na forma de `https://docs.djangoproject.com/search/?q=forms&release=1`.

`GET` e `POST` são tipicamente usados para propósitos distintos.

Qualquer requisição que pode ser usada para alterar o estado do sistema - por exemplo, uma requisição que faz alterações no banco de dados - deve usar `POST`. O `GET` deve ser usado somente para requisições que não afetam o estado do sistema.

O `GET` também não é adequado para formulários com senhas, porque a senha apareceria na URL, e portanto, também no histórico do navegador web e logs do servidor, tudo em texto puro. Nem mesmo seria adequado para grandes quantidade de dados, ou para dados binários, como uma imagem. Uma aplicação web que usa as requisições to tipo `GET` para formulários de administração é um risco de segurança: pode ser fácil para um ataque imitar uma requisição de um formulário para ter acesso a partes sensíveis do sistema. O `POST` juntamente com outras proteções como a proteção CSRF do Django oferece mais controle sobre o acesso.

Por outro lado, o `GET` é adequado para coisas como um formulário web de busca, porque a URL que represente uma requisição do tipo `GET` pode ser facilmente adicionado a lista de favoritos, comparilhada ou reenviada.

## Regras do Django em formulários

Lidar com formulários é uma coisa complexa. Considere o admin do Django, onde inúmeros itens de dados de diferentes tipos precisam ser preparados para serem visualizados em um formulário, renderizados como HTML, editado usando uma interface conveniente, retornados ao servidor, validados e limpos, e então salvos ou passados adiante para mais processamento.

A funcionalidade de formulários do Django pode simplificar e automatizar uma boa parte deste trabalho, e pode também fazer isso de maneira mais segura que a maioria dos programadores poderiam ser capazes de fazer no código que escrevem.

O Django lida com três partes distintas do trabalho envolvendo formulários:

- Preparando e reestruturando os dados para torná-los prontos para rederização
- criando formulários HTML para os dados
- recebendo e processando formulário enviado e os dados vindos do cliente

É possível escrever código que faz tudo isso manualmente, mas o Django pode tomar conta de tudo isso pra você.

## Formulários no Django

Descrevemos brevemente os formulários HTML, mas um `<form>` HTML é apenas uma parte do maquinário requerido.

Dentro do contexto de uma aplicação web, um ‘formulário’ talvez se refira ao `<form>` HTML, ou a `Form` do Django que o produz, ou ao dado estruturado retornado quando este é enviado, ou ao conjunto funcional de todas essas partes.

### A classe `Form` do Django

No coração deste sistema de componentes está a classe `Form` do Django. Mais ou menos como o modelo do Django descreve a estrutura lógica de um objeto, seu comportamento, e a maneira como suas partes são apresentadas para nós, uma classe `Form` descreve um formulário e determina como este funciona e aparece.

De maneira similar que a classe de modelo mapeia os campos para o banco de dados, uma classe de formulário mapeia para os elementos `<input>` do formulário HTML. (Uma `ModelForm` mapeia os campos de uma classe de modelo para elementos `<input>` do formulário HTML através da `Form`; o admin do Django é baseado nisso.)

Os campos dos formulários são eles próprios classes; eles manipulam dados do formulário e fazem validações quando o formulário é enviado. A `DateField` e a `FileField` lidam com tipos de dados muito diferentes e tem que fazer coisas diferentes com isso.

Um campo de formulário, para o usuário, é representado como um “widget” HTML - um pedaço do maquinário de interface do usuário. Cada campo tem uma classe de Widget padrão, mas isso pode ser sobrescrito quando requerido.

### Instanciando, processando, e renderizando formulários

Quando renderizar um objeto no Django, em geral:

1. pegamos o objeto na “view” (lido no banco de dados, por exemplo)
2. o passamos para o “context” do template
3. expandimos para a marcação HTML usando variáveis de template

Mostrar um formulário em um template envolve quase o mesmo trabalho que mostrar qualquer outro tipo de objeto, mas existem algumas diferenças chave.

No caso de uma instância de modelo que não contém nenhum dado, é raramente útil ou talvez nunca seja útil para fazer nada com isso no template. Por outro lado, faz todo o sentido, mostrar um formulário vazio - que é o que fazemos quando queremos que o usuário o preencha.

Então quando lidamos com uma instância de modelo em uma “view”, nós tipicamente a recuperamos do banco de dados. Quando lidamos com um formulário, nós tipicamente o instanciamos na “view”.

Quando nós instanciamos um formulário, nós podemos optar por deixá-lo vazio ou o pré-preenchemos, por exemplo com:

- dados vindos de uma instância de modelo salva previamente (como no caso dos formulários do admin para edição)
- dados que tenhamos coletado de outras fontes
- dados recebidos de uma prévia submissão de formulário

O último destes casos é o mais interessante, porque é o que torna possível para um usuário não somente ler um site web, mas enviar informação de volta a ele.

## Construindo um formulário

### O trabalho que tem que ser feito

Suponha queira criar um formulário simples no seu site web, de modo a obter o nome do usuário. Você precisaria de algo como isso aqui no seu template:

    <form action="/your-name/" method="post">
        <label for="your_name">Your name: </label>
        <input id="your_name" type="text" name="your_name" value="{{ current_name }}">
        <input type="submit" value="OK">
    </form>

Isso diz ao navegador web para retornar os dados do form para a URL `/your-name/`, usando o métodos `POST`. Ele irá mostrar um campo, chamado “Your name:”, e um botão com um “OK”. Se o “context” do template contiver uma variável chamada `current_name`, esta será usada para pré-preencher o campo `your_name`.

Você irá precisar uma “view” que renderiza o template contendo o formulário HTML, e que pode fornecer o campo `current_name` apropriadamente.

Quando o formulário é submetido, a requisição do tipo `POST` a qual é enviada ao servidor irá conter os dados do formulário.

Agora você irá também precisar de uma “view” que corresponda aquela URL `/your-name/` a qual irá encontrar o par chave/valor apropriado na requisição e então processá-lo.

Este é um formulário muito simples. Na prática, um formulário pode conter dezenas ou centenas de campos, muitos dos quais talvez precisem ser pré-preenchidos, e talvez nós esperamos que o usuário trabalhe através do ciclo de edição e submissão muitas vezes antes de concluir a operação.

Nós podemos requerer que alguma validação ocorra no navegador web, mesmo antes do formulário ser submetido; nós podemos querer usar campos bem mais complexos, que possibilite ao usuário selecionar uma data de um calendário e assim por diante.

Neste ponto é muito mais fácil ter o Django fazendo a maior parte deste trabalho para nós.

### Construindo um formulário no Django

#### A classe `Form`

Nós já sabemos como queremos que o nosso formulário HTML se pareça. Nosso ponto de início para isso no Django é este:

forms.py

    from django import forms

    class NameForm(forms.Form):
        your_name = forms.CharField(label='Your name', max_length=100)

Este código define uma classe `Form` com um único campo (`your_name`). Nós aplicamos uma etiqueta ao campo mais legível a seres humanos, a qual irá aparecer na `<label>` quando for renderizado (embora neste caso o `label` que especificamos é o mesmo que seria gerado automaticamente se o tivéssemos omitido).

O tamanho máximo do conteúdo do campo é definido pelo `max_length`. Isso faz duas coisas. Define a `maxlength="100"` no `<input>` HTML (então o navegador web impedirá que o usuário entre com um número de caracteres maio que aquele definido). Isso também significa que quando o Django receber o form de volta do navegador, o Django validará o comprimento do dado.

Uma instância da `Form` tem um método `is_valid()`, o qual executa rotinas de validações para todos os campos. Quando este método é chamado, se todos os campos contiverem dados válidos, ele irá:

- retornar `True`
- colocar os dados do formulário no atributo `cleaned_data` do formulário.

O formulário, quando renderizado pela primeira vez, se parecerá com:

    <label for="your_name">Your name: </label>
    <input id="your_name" type="text" name="your_name" maxlength="100" required>

Repare que não estão incluídas as tags `<form>`, ou o botão de submit. Teremos que fornecê-los nós mesmos no template.

#### A “view”

Os dados de formulários enviados para um site Django são processados por uma “view”, geralmente a mesma “view” que publica o formulário. Isso nos permiti reutilizar parte da mesma lógica.

Para lidar com o formulário precisamos instanciá-lo na “view” da URL onde queremos que seja publicado:

views.py

    from django.http import HttpResponseRedirect
    from django.shortcuts import render

    from .forms import NameForm

    def get_name(request):
        # if this is a POST request we need to process the form data
        if request.method == 'POST':
            # create a form instance and populate it with data from the request:
            form = NameForm(request.POST)
            # check whether it's valid:
            if form.is_valid():
                # process the data in form.cleaned_data as required
                # ...
                # redirect to a new URL:
                return HttpResponseRedirect('/thanks/')

        # if a GET (or any other method) we'll create a blank form
        else:
            form = NameForm()

        return render(request, 'name.html', {'form': form})

Se chegarmos a essa “view” com uma requisição do tipo `GET`, ela irá criar uma instância vazia de formulário e colocá-lo no “context” do template para renderizá-lo. Isso é o que esperamos que aconteça quando visitarmos a URL pela primeira vez.

Se o formulário for submetido usando uma requisição do tipo `POST`, a “view” irá mais uma vez criar uma instância do formulário e preenchê-la com dados vindos da requisição `form = NameForm(request.POST)`. Isso é chamado “carregar dados no formulário” (ele é agora um “bound form”).

Chamamos o método `is_valid()``do formulário; se não é ``True`, nós retornamos ao template com o formulário. Desta vez o formulário não está mais vazio (unbound) então o formulário HTML será preenchido com os dados previamente submetidos, onde podem ser editados e corrigidos quando necessário.

Se `is_valid()` é `True`, seremos capazes de encontrar todos os dados do formulário no atributo `cleaned_data`. Podemos usar estes dados para atualizar o banco de dados ou fazer outro processamento antes de enviar um redirecionamento HTTP para o navegador dizendo onde ir a seguir.

#### O template

We don’t need to do much in our `name.html` template:

    <form action="/your-name/" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Submit">
    </form>

Todos os campos dos formulário e seus atributos serão desempacotados dentro da marcação HTML vindos do `{{ form }}` através da linguagem de templates do Django.

Formulários e a proteção contra “Falsificação de solicitação entre sites”

O Django traz uma proteção contra falsificação de solicitação entre sites (CSRF em Inglês). Quando se submete um formulário através de um `POST` com a proteção CSRF habilitada você deve usar a template tag `csrf_token` como no exemplo anterior. Porém, uma vez que a proteção CSRF não está diretamente ligada a formulários em templates, essa tag é omitida dos próximos exemplos neste documento.

Tipos de entradas HTML5 e validação do navegador

If your form includes a `URLField`, an `EmailField` or any integer field type, Django will use the `url`, `email` and `number` HTML5 input types. By default, browsers may apply their own validation on these fields, which may be stricter than Django’s validation. If you would like to disable this behavior, set the `novalidate` attribute on the `form` tag, or specify a different widget on the field, like `TextInput`.

Nós agora temos um formulário web funcional, descrito pela `Form` do Django, processado pela “view”, e renderizado como um `<form>` HTML.

Isso é tudo o que você precisa para iniciar, mas o framework de formulários lhe dá muito mais. Uma vez que tenha entendido o básico dos processos descritos acima, você deve estar preparado para entender outras características do sistema de formulários e pronto par aprender um pouco mais sobre maquinário por de trás disso.

## Mais sobre as classes de `Form` do Django

All form classes are created as subclasses of either `django.forms.Form` or `django.forms.ModelForm`. You can think of `ModelForm` as a subclass of `Form`. `Form` and `ModelForm` actually inherit common functionality from a (private) `BaseForm` class, but this implementation detail is rarely important.

Modelos e Formulários

In fact if your form is going to be used to directly add or edit a Django model, a ModelForm can save you a great deal of time, effort, and code, because it will build a form, along with the appropriate fields and their attributes, from a `Model` class.

### Bound and unbound form instances

The distinction between Bound and unbound forms is important:

- An unbound form has no data associated with it. When rendered to the user, it will be empty or will contain default values.
- A bound form has submitted data, and hence can be used to tell if that data is valid. If an invalid bound form is rendered, it can include inline error messages telling the user what data to correct.

The form’s `is_bound` attribute will tell you whether a form has data bound to it or not.

### More on fields

Consider a more useful form than our minimal example above, which we could use to implement “contact me” functionality on a personal website:

forms.py

    from django import forms

    class ContactForm(forms.Form):
        subject = forms.CharField(max_length=100)
        message = forms.CharField(widget=forms.Textarea)
        sender = forms.EmailField()
        cc_myself = forms.BooleanField(required=False)

Our earlier form used a single field, `your_name`, a `CharField`. In this case, our form has four fields: `subject`, `message`, `sender` and `cc_myself`. `CharField`, `EmailField` and `BooleanField` are just three of the available field types; a full list can be found in Form fields.

#### Widgets

Each form field has a corresponding Widget class, which in turn corresponds to an HTML form widget such as `<input type="text">`.

In most cases, the field will have a sensible default widget. For example, by default, a `CharField` will have a `TextInput` widget, that produces an `<input type="text">` in the HTML. If you needed `<textarea>` instead, you’d specify the appropriate widget when defining your form field, as we have done for the `message` field.

#### Dados do campo

Whatever the data submitted with a form, once it has been successfully validated by calling `is_valid()` (and `is_valid()` has returned `True`), the validated form data will be in the `form.cleaned_data` dictionary. This data will have been nicely converted into Python types for you.

Nota

You can still access the unvalidated data directly from `request.POST` at this point, but the validated data is better.

In the contact form example above, `cc_myself` will be a boolean value. Likewise, fields such as `IntegerField` and `FloatField` convert values to a Python `int` and `float` respectively.

Here’s how the form data could be processed in the view that handles this form:

views.py

    from django.core.mail import send_mail

    if form.is_valid():
        subject = form.cleaned_data['subject']
        message = form.cleaned_data['message']
        sender = form.cleaned_data['sender']
        cc_myself = form.cleaned_data['cc_myself']

        recipients = ['info@example.com']
        if cc_myself:
            recipients.append(sender)

        send_mail(subject, message, sender, recipients)
        return HttpResponseRedirect('/thanks/')

Dica

For more on sending email from Django, see Enviando e-mail.

Some field types need some extra handling. For example, files that are uploaded using a form need to be handled differently (they can be retrieved from `request.FILES`, rather than `request.POST`). For details of how to handle file uploads with your form, see Binding uploaded files to a form.

## Working with form templates

All you need to do to get your form into a template is to place the form instance into the template context. So if your form is called `form` in the context, `{{ form }}` will render its `<label>` and `<input>` elements appropriately.

### Form rendering options

Additional form template furniture

Don’t forget that a form’s output does not include the surrounding `<form>` tags, or the form’s `submit` control. You will have to provide these yourself.

There are other output options though for the `<label>`/`<input>` pairs:

- `{{ form.as_table }}` will render them as table cells wrapped in `<tr>` tags
- `{{ form.as_p }}` will render them wrapped in `<p>` tags
- `{{ form.as_ul }}` will render them wrapped in `<li>` tags

Note that you’ll have to provide the surrounding `<table>` or `<ul>` elements yourself.

Here’s the output of `{{ form.as_p }}` for our `ContactForm` instance:

    <p><label for="id_subject">Subject:</label>
        <input id="id_subject" type="text" name="subject" maxlength="100" required></p>
    <p><label for="id_message">Message:</label>
        <textarea name="message" id="id_message" required></textarea></p>
    <p><label for="id_sender">Sender:</label>
        <input type="email" name="sender" id="id_sender" required></p>
    <p><label for="id_cc_myself">Cc myself:</label>
        <input type="checkbox" name="cc_myself" id="id_cc_myself"></p>

Note that each form field has an ID attribute set to `id_<field-name>`, which is referenced by the accompanying label tag. This is important in ensuring that forms are accessible to assistive technology such as screen reader software. You can also customize the way in which labels and ids are generated.

See Outputting forms as HTML for more on this.

### Rendering fields manually

We don’t have to let Django unpack the form’s fields; we can do it manually if we like (allowing us to reorder the fields, for example). Each field is available as an attribute of the form using `{{ form.name_of_field }}`, and in a Django template, will be rendered appropriately. For example:

    {{ form.non_field_errors }}
    <div class="fieldWrapper">
        {{ form.subject.errors }}
        <label for="{{ form.subject.id_for_label }}">Email subject:</label>
        {{ form.subject }}
    </div>
    <div class="fieldWrapper">
        {{ form.message.errors }}
        <label for="{{ form.message.id_for_label }}">Your message:</label>
        {{ form.message }}
    </div>
    <div class="fieldWrapper">
        {{ form.sender.errors }}
        <label for="{{ form.sender.id_for_label }}">Your email address:</label>
        {{ form.sender }}
    </div>
    <div class="fieldWrapper">
        {{ form.cc_myself.errors }}
        <label for="{{ form.cc_myself.id_for_label }}">CC yourself?</label>
        {{ form.cc_myself }}
    </div>

Complete `<label>` elements can also be generated using the `label_tag()`. For example:

    <div class="fieldWrapper">
        {{ form.subject.errors }}
        {{ form.subject.label_tag }}
        {{ form.subject }}
    </div>

#### Rendering form error messages

The price of this flexibility is a bit more work. Until now we haven’t had to worry about how to display form errors, because that’s taken care of for us. In this example we have had to make sure we take care of any errors for each field and any errors for the form as a whole. Note `{{ form.non_field_errors }}` at the top of the form and the template lookup for errors on each field.

Using `{{ form.name_of_field.errors }}` displays a list of form errors, rendered as an unordered list. This might look like:

    <ul class="errorlist">
        <li>Sender is required.</li>
    </ul>

The list has a CSS class of `errorlist` to allow you to style its appearance. If you wish to further customize the display of errors you can do so by looping over them:

    {% if form.subject.errors %}
        <ol>
        {% for error in form.subject.errors %}
            <li><strong>{{ error|escape }}</strong></li>
        {% endfor %}
        </ol>
    {% endif %}

Non-field errors (and/or hidden field errors that are rendered at the top of the form when using helpers like `form.as_p()`) will be rendered with an additional class of `nonfield` to help distinguish them from field-specific errors. For example, `{{ form.non_field_errors }}` would look like:

    <ul class="errorlist nonfield">
        <li>Generic validation error</li>
    </ul>

See The Forms API for more on errors, styling, and working with form attributes in templates.

### Looping over the form’s fields

If you’re using the same HTML for each of your form fields, you can reduce duplicate code by looping through each field in turn using a `{% for %}` loop:

    {% for field in form %}
        <div class="fieldWrapper">
            {{ field.errors }}
            {{ field.label_tag }} {{ field }}
            {% if field.help_text %}
            <p class="help">{{ field.help_text|safe }}</p>
            {% endif %}
        </div>
    {% endfor %}

Useful attributes on `{{ field }}` include:

`{{ field.label }}`
  The label of the field, e.g. `Email address`.
`{{ field.label_tag }}`

  The field’s label wrapped in the appropriate HTML `<label>` tag. This includes the form’s `label_suffix`. For example, the default `label_suffix` is a colon:

      <label for="id_email">Email address:</label>

`{{ field.id_for_label }}`
  The ID that will be used for this field (`id_email` in the example above). If you are constructing the label manually, you may want to use this in lieu of `label_tag`. It’s also useful, for example, if you have some inline JavaScript and want to avoid hardcoding the field’s ID.
`{{ field.value }}`
  The value of the field. e.g `someone@example.com`.
`{{ field.html_name }}`
  The name of the field that will be used in the input element’s name field. This takes the form prefix into account, if it has been set.
`{{ field.help_text }}`
  Any help text that has been associated with the field.
`{{ field.errors }}`
  Outputs a `<ul class="errorlist">` containing any validation errors corresponding to this field. You can customize the presentation of the errors with a `{% for error in field.errors %}` loop. In this case, each object in the loop is a string containing the error message.
`{{ field.is_hidden }}`
  This attribute is `True` if the form field is a hidden field and `False` otherwise. It’s not particularly useful as a template variable, but could be useful in conditional tests such as:

    {% if field.is_hidden %}
       {# Do something special #}
    {% endif %}

`{{ field.field }}`
  The `Field` instance from the form class that this `BoundField` wraps. You can use it to access `Field` attributes, e.g. `{{ char_field.field.max_length }}`.

Ver também

For a complete list of attributes and methods, see `BoundField`.

#### Looping over hidden and visible fields

If you’re manually laying out a form in a template, as opposed to relying on Django’s default form layout, you might want to treat `<input type="hidden">` fields differently from non-hidden fields. For example, because hidden fields don’t display anything, putting error messages “next to” the field could cause confusion for your users – so errors for those fields should be handled differently.

Django provides two methods on a form that allow you to loop over the hidden and visible fields independently: `hidden_fields()` and `visible_fields()`. Here’s a modification of an earlier example that uses these two methods:

    {# Include the hidden fields #}
    {% for hidden in form.hidden_fields %}
    {{ hidden }}
    {% endfor %}
    {# Include the visible fields #}
    {% for field in form.visible_fields %}
        <div class="fieldWrapper">
            {{ field.errors }}
            {{ field.label_tag }} {{ field }}
        </div>
    {% endfor %}

This example does not handle any errors in the hidden fields. Usually, an error in a hidden field is a sign of form tampering, since normal form interaction won’t alter them. However, you could easily insert some error displays for those form errors, as well.

### Reusable form templates

If your site uses the same rendering logic for forms in multiple places, you can reduce duplication by saving the form’s loop in a standalone template and using the `include` tag to reuse it in other templates:

    # In your form template:
    {% include "form_snippet.html" %}

    # In form_snippet.html:
    {% for field in form %}
        <div class="fieldWrapper">
            {{ field.errors }}
            {{ field.label_tag }} {{ field }}
        </div>
    {% endfor %}

If the form object passed to a template has a different name within the context, you can alias it using the `with` argument of the `include` tag:

    {% include "form_snippet.html" with form=comment_form %}

If you find yourself doing this often, you might consider creating a custom inclusion tag.

## Further topics

This covers the basics, but forms can do a whole lot more:

- Formsets
  - Using initial data with a formset
  - Limiting the maximum number of forms
  - Formset validation
  - Validating the number of forms in a formset
  - Dealing with ordering and deletion of forms
  - Adding additional fields to a formset
  - Passing custom parameters to formset forms
  - Customizing a formset’s prefix
  - Using a formset in views and templates
- Creating forms from models
  - `ModelForm`
  - Model formsets
  - Inline formsets
- Form Assets (the `Media` class)
  - Assets as a static definition
  - `Media` as a dynamic property
  - Paths in asset definitions
  - Objetos de `Media`
  - `Media` on Forms

Ver também

The Forms Reference
  Covers the full API reference, including form fields, form widgets, and form and field validation.