Criando formulários a partir de models

ModelForm

Se você está construindo uma aplicação baseada em banco de dados, existe uma grande chance de que seus formulários corresponderão com os seus modelos Django. Por exemplo, você tem um modelo BlogComment, e quer criar um formulário que possibilite que as pessoas enviem comentários. Neste caso, seria redundante definir os tipos de campo no seu formulário, porque isso já foi feito no seu modelo.

Por este motivo, o Django disponibiliza uma classe de ajuda que possibilita a criação de uma classe Form a partir de um modelo Django.

Por exemplo:

>>> from django.forms import ModelForm

# Cria a classe de formulário
>>> class ArticleForm(ModelForm):
...     class Meta:
...         model = Article

# Criando um formulário para adicionar um artigo.
>>> form = ArticleForm()

# Criando um formulário para atualizar dados de um artigo.
>>> article = Article.objects.get(pk=1)
>>> form = ArticleForm(instance=article)

Tipos de campos

A classe Form gerada terá um campo de formulário para cada campo de modelo. Cada campo de modelo tem um campo de formulário correspondente padrão. Por exemplo, um CharField num modelo é representado como um CharField num formulário. Um ManyToManyField no modelo é representado como um MultipleChoiceField. Segue uma lista completa de conversões:

Campo de modelo Campo de formulário
AutoField Não é representado no formulário
BooleanField BooleanField
CharField CharField com max_length igual ao valor de max_length do campo do modelo
CommaSeparatedIntegerField CharField
DateField DateField
DateTimeField DateTimeField
DecimalField DecimalField
EmailField EmailField
FileField FileField
FilePathField CharField
FloatField FloatField
ForeignKey ModelChoiceField (veja abaixo)
ImageField ImageField
IntegerField IntegerField
IPAddressField IPAddressField
ManyToManyField ModelMultipleChoiceField (veja abaixo)
NullBooleanField CharField
PhoneNumberField USPhoneNumberField (de django.contrib.localflavor.us)
PositiveIntegerField IntegerField
PositiveSmallIntegerField IntegerField
SlugField CharField
SmallIntegerField IntegerField
TextField CharField com widget=forms.Textarea
TimeField TimeField
URLField URLField com verify_exists igual ao valor de verify_exists do campo do modelo
XMLField CharField com widget=Textarea
O campo de formulário FloatField juntamente com os campos de fomulário e de modelo DecimalField são novos no Django 1.0.

Como esperado, os campos de modelo do tipo ForeignKey e ManyToManyField são casos especiais:

  • ForeignKey é representado por django.forms.ModelChoiceField, que é um ChoiceField em que choices é um QuerySet do modelo.
  • ManyToManyField é representado por django.forms.ModelMultipleChoiceField, que é um MultipleChoiceField em que choices é um QuerySet do modelo.

Além disso, cada campo de formulário gerado tem os valores de atributos definidos como asseguir:

  • Se um campo de modelo tem blank=True, então o valor de required será False no campo de formulário. Caso contrário, required=True.
  • O atributo label do campo de formulário será igual ao verbose_name do campo de modelo, com o primeiro caractere em maiúsculo.
  • O help_text do campo de formulário é igual ao help_text do campo de modelo.
  • Se o campo de modelo tem o atributo choices definido, então o widget do campo de formulário será o Select, com a lista de opções vindas do atributo choices do campo de modelo. As opções normalmente incluirão o valor em branco, que é selecionado por padrão. Se o campo é requerido, isso força o usuário a fazer uma escolha. O valor em branco não será incluído se o campo de modelo tem atributo blank=False e um valor de default explícito (em vez disso o valor de default será selecionado inicialmente).

Finalmente, note que você pode redefinir o campo de formulário utilizado por um determinado modelo. Veja Redefinindo os tipos de campo padrão abaixo.

Um exemplo completo

Considere este conjunto de modelos:

from django.db import models
from django.forms import ModelForm

TITLE_CHOICES = (
    ('MR', 'Mr.'),
    ('MRS', 'Mrs.'),
    ('MS', 'Ms.'),
)

class Author(models.Model):
    name = models.CharField(max_length=100)
    title = models.CharField(max_length=3, choices=TITLE_CHOICES)
    birth_date = models.DateField(blank=True, null=True)

    def __unicode__(self):
        return self.name

class Book(models.Model):
    name = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)

class AuthorForm(ModelForm):
    class Meta:
        model = Author

class BookForm(ModelForm):
    class Meta:
        model = Book

Com estes modelos, as subclasses de ModelForm acima seriam equivalentes a isto (a única diferença sendo o método save(), que discutiremos daqui a pouco.):

class AuthorForm(forms.Form):
    name = forms.CharField(max_length=100)
    title = forms.CharField(max_length=3,
                widget=forms.Select(choices=TITLE_CHOICES))
    birth_date = forms.DateField(required=False)

class BookForm(forms.Form):
    name = forms.CharField(max_length=100)
    authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())

O método save()

Todo formulário produzido por ModelForm tem também um método save(). Este método cria e grava um objeto no banco de dados a partir dos dados atrelados ao formulário. Uma subclasse de ModelForm pode aceitar uma instância de modelo existente como uma argumento nomeado instance; se este argumento é fornecido, o save() irá atualizar a instância. Se não é fornecido, o save() criará uma nova instância do modelo especificado:

# Cria uma instância de formulário com dados do POST.
>>> f = ArticleForm(request.POST)

# Grava um novo objeto Article com os dados do formulário.
>>> new_article = f.save()

# Cria um formulário para editar um Article existente.
>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(instance=a)
>>> f.save()

# Cria um formulário para editar um Article existente, mas
# usa os dados do POST para popular o formulário.
>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(request.POST, instance=a)
>>> f.save()

Note que save() irá levantar uma exceção ValueError se os dados no formulário não validarem – ou seja if form.errors.

Este método save() aceita um argumento nomeado opcional commit, que aceita ou True ou False. Se você chamar save() com commit=False, então ele devolverá um objeto que ainda não foi gravado no banco de dados. Neste caso, é sua responsabilidade chamar save() na instância de modelo. Isso é útil se você quer fazer algum custom processamento customizado no objeto antes de gravá-lo, ou se você quer usar um umas das opções de gravação de modelo especializadas. commit é True por padrão.

Um efeito colateral no uso de commit=False é notado quando o seu modelo tem um relacionamento de muitos para muitos com outro modelo. Se seu modelo tem um relacionamento de muitos para muitos e você especifica commit=False quando vai gravar um formulário, o Django não pode gravar od dados para o relacionamento de muitos para muitos imediatamente. Isso se deve ao fato de não ser possível gravar os dados de muitos para muitos para uma instância que ainda não existe no banco de dados.

Para contornar este problema, cada vez que você grava um formulário usando commit=False, o Django adiciona um método save_m2m() para a sua subclasse de ModelForm. Depois de de gravar manualmente a instância produzida pelo formulário, você pode chamar save_m2m() para gravar os dados de muitos para muitos do formulário. Por exemplo:

# Cria uma instância de formulário com os dados de POST.
>>> f = AuthorForm(request.POST)

# Cria, mas não grava a nova instância de Author.
>>> new_author = f.save(commit=False)

# Modifica o Author de alguma maneira.
>>> new_author.some_field = 'some_value'

# Grava a nova instância.
>>> new_author.save()

# Agora, grava od dados de muitos para muitos para o formulário.
>>> f.save_m2m()

Só é necessário chamar o save_m2m() se você usar save(commit=False). Quando você simplesmente usa o save() num formulário, todos os dados – incluindo os dados de muitos para muitos – são gravados sem a necessidade de chamadas a nenhum método adicional. Por exemplo:

# Cria uma instância de formulário com os dados de POST.
>>> a = Author()
>>> f = AuthorForm(request.POST, instance=a)

# Cria e grava a nova instância de Author. Não há necessidade de fazer
# nada mais.
>>> new_author = f.save()

A não ser pelos métodos save() e save_m2m(), um ModelForm funciona exatamente igual a qualquer outro formulário de forms. Por exemplo, o método is_valid()` é utilizado para validar os dados, o método is_multipart() para determinar se um formulário requer upload de arquivo multipart (e se request.FILES deve ser passado ao formulário), etc. Veja Vinculando arquivos enviados a um formulário para mais informação.

Usando somente alguns campos no formulário

Em alguns casos, você não quer que todos os campos do modelo apareçam no formulário gerado. Existem três maneiras de dizer ao ModelForm para usar somente alguns campos do modelo:

  1. Coloque editable=False no campo do modelo. Como resultado, qualquer formulário criado via ModelForm não incluirá este campo.
  2. Use o atributo fields da classe interna Meta do ModelForm. Esse atributo, se especificado, deve ser uma lista de nomes de campos a serem incluídos no formulário.
  3. Use o atributo exclude da classe interna Meta do ModelForm. Esse atributo, se especificado, deve ser uma lista de nomes de campos a serem excluídos do formulário.

Por exemplo, se você quer que um formulário para o modelo Author (definido acima) tenha somente os campos name e title, você especificaria fields ou exclude assim:

class PartialAuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title')

class PartialAuthorForm(ModelForm):
    class Meta:
        model = Author
        exclude = ('birth_date',)

Já que o modelo Author tem somente três campos, ‘name’, ‘title’, e ‘birth_date’, os formulários acima conterão exatamente os mesmos campos.

Note

Se você especifica fields ou exclude na criação de um formulário com ModelForm, então na chamada do método save(), não serão atribuídos valores aos campos que não constam do formulário resultante. O Django impedirá qualquer tentativa de gravar um modelo incompleto, então se o modelo não permite que os campos faltantes sejam vazios, e não existe um valor padrão definido para eles, qualquer tentativa de chamar save() num ModelForm com campos faltantes não funcionará. Para evitar esse erro, você deve instanciar seu modelo com valores iniciais para os campos vazios, porém obrigatórios:

author = Author(title='Mr')
form = PartialAuthorForm(request.POST, instance=author)
form.save()

Alternatively, you can use save(commit=False) and manually set any extra required fields:

form = PartialAuthorForm(request.POST)
author = form.save(commit=False)
author.title = 'Mr'
author.save()

Veja a seção sobre gravação de formulários para mais detalhes no uso de save(commit=False).

Redefinindo os tipos de campo padrão

Os tipos de campos padrão, como descritos na tabela Tipos de campos acima, são padrões sensatos. Se você tem um DateField no seu modelo, existem grandes chances dq que você queira que ele seja representado como um DateField no seu formulário. Mas o ModelForm te dá a flexibilidade de mudar o campo de formulário para um determinado campo de modelo. Isso é feito de maneira declarativa especificando os campos como faria num Form normal. Campos declarados redefinirão os campós padrões gerados pelo uso do atributo model.

Por exemplo, se você quiser usar MyDateFormField para o campo pub_date, faça o seguinte:

>>> class ArticleForm(ModelForm):
...     pub_date = MyDateFormField()
...
...     class Meta:
...         model = Article

Se quiser redefiner um widget padrão de um campo, então especifique o parâmetro widget quando declarar o campo de formulário:

>>> class ArticleForm(ModelForm):
...     pub_date = DateField(widget=MyDateWidget())
...
...     class Meta:
...         model = Article

Sobrescrevendo o método clean()

Você pode sobrescrever o método clean() em um formulário de modelo para fornecer informações adicionais como uma validação, da mesma forma que faria num formulário normal.

In this regard, model forms have two specific characteristics when compared to forms:

Por padrão o método clean() valida a unicidade dos campos que são marcados como unique, unique_together ou unique_for_date|month|year no modelo. Portanto, se você gostaria de sobrescrever o método clean() e manter a validação padrão, você deve chamar o método da clean() da classe pai.

Also, a model form instance bound to a model object will contain a self.instance attribute that gives model form methods access to that specific model instance.

Herança de formulário

Como nos formulários básicos, você pode extender e reutilizar ModelForms através da herança. Isso é útil se você precisa declarar campos ou métodos adicionais em uma classe pai para uso em alguns formulários derivados de modelos. Por exemplo, usando a classe ArticleForm anterior:

>>> class EnhancedArticleForm(ArticleForm):
...     def clean_pub_date(self):
...         ...

Isso cria um formulário que se comporta da mesma maneira que ArticleForm, exceto por alguma validação e limpeza de dados adicional para o campo pub_date.

Você pode criar uma subclasse da classe interna Meta da classe pai se você quer mudar as listas Meta.fields ou Meta.excludes:

>>> class RestrictedArticleForm(EnhancedArticleForm):
...     class Meta(ArticleForm.Meta):
...         exclude = ['body']

Isso adiciona o método de EnhancedArticleForm e modifica o ArticleForm.Meta original para remover um campo.

Entretanto, existem algumas coisas a serem notadas.

  • As regras normais de resolução de nomes Python se aplicam. Se você tem múltiplas classes base que declaram uma classe interna Meta, somente a primeira será utilizada. Isso significa o Meta do filho, se existir, caso contrário o Meta do primeiro pai, etc.
  • Pela mesma razão, uma subclasse não pode herdar de ModelForm e Form simultaneamente.

É bem provável que estas notas não te afetarão, a não ser que esteja tentando fazer algo complexo utilizando subclasses.

Model Formsets

Como nos formsets comuns, o Django fornece um par de classes avançadas de formset que tornam facil trabalhar com modelos do Django. Vamos reutilizar o modelo Author do exemplo acima:

>>> from django.forms.models import modelformset_factory
>>> AuthorFormSet = modelformset_factory(Author)

Isso criará um formset que é capaz de funcionar com os dados associados ao modelo Author que funciona exatamente igual a um formset comum:

>>> formset = AuthorFormSet()
>>> print formset
<input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS" />
<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100" /></td></tr>
<tr><th><label for="id_form-0-title">Title:</label></th><td><select name="form-0-title" id="id_form-0-title">
<option value="" selected="selected">---------</option>
<option value="MR">Mr.</option>
<option value="MRS">Mrs.</option>
<option value="MS">Ms.</option>
</select></td></tr>
<tr><th><label for="id_form-0-birth_date">Birth date:</label></th><td><input type="text" name="form-0-birth_date" id="id_form-0-birth_date" /><input type="hidden" name="form-0-id" id="id_form-0-id" /></td></tr>

Note

Uma coisa para se notar é que modelformset_factory usa formset_factory para gerar formsets. Isto significa que um formeset de model é somente uma extensão de um formset básico que sabe como interagir com um model em particular.

Mudando o queryset

Por padrão quando você cria um formset de um modelo o formset irá usar um queryset que inclui todos os objetos no modelo (ex: Author.objects.all()). Você pode sobrescrever esse comportamento usando o argumento queryset:

>>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))

Alternativamente, você pode criar uma subclasse que defina o self.queryset no __init__:

from django.forms.models import BaseModelFormSet

class BaseAuthorFormSet(BaseModelFormSet):
    def __init__(self, *args, **kwargs):
        self.queryset = Author.objects.filter(name__startswith='O')
        super(BaseAuthorFormSet, self).__init__(*args, **kwargs)

Então, passe sua classe BaseAuthorFormSet para a função factory:

>>> AuthorFormSet = modelformset_factory(Author, formset=BaseAuthorFormSet)

Controlando quais campos são usados com fields e exclude

Por padrão um model formset usará todos os campos do model, que não estão marcados com editable=False, Entretanto, isto pode ser sobrescrito no nível do formset:

>>> AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))

Usando fields você irá restringir o formset para usar somente os campos fornecidos. Alternativamente, você pode ter uma abordagem de “out-put”, especificando quais campos serão excluídos:

>>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',))

Usando exclude você irá evistar que dados campos sejam usados em um formset.

Gravando objetos num formset

Como num ModelForm você pode gravar os dados no objeto do modelo. Isso é feito com o método save() do formset:

# Cria uma instância de formset com os dados do POST.
>>> formset = AuthorFormSet(request.POST)

# Supondo que tudo está válido, grave os dados
>>> instances = formset.save()

O método save() devolverá as instâncias que foram gravadas no banco de dados. Se uma instância não mudar seus nos dados atrelados ela não será gravada no banco e não será encontrada no valor de retorn (instances no exemplo acima).

Pass commit=False to return the unsaved model instances:

# não grava no banco de dados
>>> instances = formset.save(commit=False)
>>> for instance in instances:
...     # faz alguma coisa com a instância
...     instance.save()

Isso dá a habilidade de anexar dados às instâncias antes de gravá-las no banco de dados. Se seu formset contém um ManyToManyField você precisará também chamar formset.save_m2m() para assegurar que os relacionamentos de muitos para muitos serão gravados apropriadamente.

Limitando o número de objetos editáveis

Como em formsets comuns você pode usar um parâmetro max_num no modelformset_factory para limitar o número de formulários mostrados. Com formsets de modelo, isso limitará apropriadamente a query para selecionar somente o máximo de objetos necessários:

>>> Author.objects.order_by('name')
[<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>]

>>> AuthorFormSet = modelformset_factory(Author, max_num=2, extra=1)
>>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
>>> formset.initial
[{'id': 1, 'name': u'Charles Baudelaire'}, {'id': 3, 'name': u'Paul Verlaine'}]

Se o valor de max_num é maior que o número de objetos retornados, formulários em branco extra serão adicionados ao formset, tão logo o total de formulários não exceda max_num:

>>> AuthorFormSet = modelformset_factory(Author, max_num=4, extra=2)
>>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
>>> for form in formset.forms:
...     print form.as_table()
<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100" /><input type="hidden" name="form-0-id" value="1" id="id_form-0-id" /></td></tr>
<tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100" /><input type="hidden" name="form-1-id" value="3" id="id_form-1-id" /></td></tr>
<tr><th><label for="id_form-2-name">Name:</label></th><td><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100" /><input type="hidden" name="form-2-id" value="2" id="id_form-2-id" /></td></tr>
<tr><th><label for="id_form-3-name">Name:</label></th><td><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100" /><input type="hidden" name="form-3-id" id="id_form-3-id" /></td></tr>

Usando um model formset em uma visão

Models formsets são muito similares a formsets. Digamos que queiramos apresentar um formset para editar instâncias do modelo Author:

def manage_authors(request):
    AuthorFormSet = modelformset_factory(Author)
    if request.method == 'POST':
        formset = AuthorFormSet(request.POST, request.FILES)
        if formset.is_valid():
            formset.save()
            # Faça algo.
    else:
        formset = AuthorFormSet()
    return render_to_response("manage_authors.html", {
        "formset": formset,
    })

Como você pode ver a lógica da visão de um formset de modelo não é drasticamente diferente de como usar um formset “normal”. A única diferença é que nos chamamos formset.save() para salvar os dados no banco de dados. (Isto foi descrito acima em Gravando objetos num formset.)

Sobrescrevendo o clean() sobre um model_formset

Assim como com ModelForms, por padrão o método clean() de um model_formset irá validar se nenhum dos ítens do formset viola as restrições de unicidade do seu model (qualquer uma unique, unique_together ou unique_for_date|month|year). Se você quiser sobrescrever o método clean() de um model_formset e manter esta validação, você deve chamar o método clean da classe pai:

class MyModelFormSet(BaseModelFormSet):
    def clean(self):
        super(MyModelFormSet, self).clean()
        # exemplo de validação customizada de forms do formset:
        for form in self.forms:
            # your custom formset validation
            # sua validação personalizada de formset

Usando um queryset customizado

Como já foi dito, você pode sobrescrever o queryset padrão usado pelo model formset:

def manage_authors(request):
    AuthorFormSet = modelformset_factory(Author)
    if request.method == "POST":
        formset = AuthorFormSet(request.POST, request.FILES,
                                queryset=Author.objects.filter(name__startswith='O'))
        if formset.is_valid():
            formset.save()
            # Faça algo.
    else:
        formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
    return render_to_response("manage_authors.html", {
        "formset": formset,
    })

Note que nós passamos o argumento queryset em ambos os casos POST e GET neste exemplo.

Usando o formset no template

Já três formas de renderizar um formset num template Django.

Primeiro, você pode deixar o formset fazer a maior parte do trabalho:

<form method="POST" action="">
    {{ formset }}
</form>

Segundo, você pode manualmente renderizar o formset, mas deixe o form trabalhar por contra própria:

<form method="POST" action="">
    {{ formset.management_form }}
    {% for form in formset.forms %}
        {{ form }}
    {% endfor %}
</form>

Quando você renderizar formulários manualmente, certifique-se de renderizar o management_form como mostrado acima. Veja a documentação do management form.

Terceiro, você pode renderizar manualmente cada campo:

<form method="POST" action="">
    {{ formset.management_form }}
    {% for form in formset.forms %}
        {% for field in form %}
            {{ field.label_tag }}: {{ field }}
        {% endfor %}
    {% endfor %}
</form>

Se você optar por usar este terceiro método e você não iterar sobre os campos com um loop {% for %}, você precisará renderizar a chave primária. Por exemplo, se você renderizou os campos name e age de um model:

<form method="POST" action="">
    {{ formset.management_form }}
    {% for form in formset.forms %}
        {{ form.id }}
        <ul>
            <li>{{ form.name }}</li>
            <li>{{ form.age }}</li>
        </ul>
    {% endfor %}
</form>

Observe como é preciso, explicitamente, renderizar {{form.id}}. Isto garante que o formset do model, no caso do POST, irá funcionar perfeitamente. (Este exemplo assume uma chave primária chamada id, certifique-se de renderizá-la.)

Formsets em linha (inline)

Formsets em linha é uma pequena camada de abstração sobre os formsets de model. Este simplificam o caso de trabalhar com objetos relacionados através de uma chave estrangeira. Suponhamos que você tenha dois models:

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    author = models.ForeignKey(Author)
    title = models.CharField(max_length=100)

Se você quiser criar um formset que permita editar books pertencentes a um author em particular, você pode fazer isto:

>>> from django.forms.models import inlineformset_factory
>>> BookFormSet = inlineformset_factory(Author, Book)
>>> author = Author.objects.get(name=u'Mike Royko')
>>> formset = BookFormSet(instance=author)

Note

inlineformset_factory usa modelformset_factory e marca can_delete=True.

Mais de uma chave estrangeira para o mesmo model

Se o seu model contém mais de uma chave estrangeira para o mesmo model, você precisará resolver a ambiguidade manualmente utilizando fk_name. Por exemplo, considere o seguinte model:

class Friendship(models.Model):
    from_friend = models.ForeignKey(Friend)
    to_friend = models.ForeignKey(Friend)
    length_in_months = models.IntegerField()

Para resolver isto, você pode usar fk_name para inlineformset_factory:

>>> FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name="from_friend")

Usando um formset em linha em um view

Você pode querer prover um view que permite um usuário editar os objetos relacionados de um model. Aqui tem uma maneira de se fazer isso:

def manage_books(request, author_id):
    author = Author.objects.get(pk=author_id)
    BookInlineFormSet = inlineformset_factory(Author, Book)
    if request.method == "POST":
        formset = BookInlineFormSet(request.POST, request.FILES, instance=author)
        if formset.is_valid():
            formset.save()
            # Do something.
    else:
        formset = BookInlineFormSet(instance=author)
    return render_to_response("manage_books.html", {
        "formset": formset,
    })

Observe como passamos instance em ambos os casos POST e GET.