Sobre este documento
Este documento fornece uma introdução as funcionalidades de manipulação de formulários do Django. Para uma visão mais detalhada da API de forumulários, veja A API de formulários. Para documentação de tipos de campos disponíveis, veja Campos de formulário.
django.forms é a biblioteca de manipulação de formulários.
Embora seja possível processar submissões de formulário somente usando a classe HttpRequest do Django, usando a biblioteca de formulários fica melhor para a realização de uma série de tarefas comunus relacionadas a formulários. Usando-o, você pode:
A biblioteca trabalha com os seguintes conceitos:
A biblioteca é dissociada de outros componentes do Django, como a camada de banco de dados., views e templates. Ele invoca somente do Django settings, algumas funções helpers django.utils e hooks de internacionalização do Django (mas você não é obrigado a usar internacionalização para usar esta biblioteca).
Um objeto Form encapsula uma sequencia de campos de formulário e uma coleção de regras de validação que devem ser preenchidas para que o furmulário seja aceito. Classes Form são criadas como subclasses de django.forms.Form e fazem uso de um estilo declarativo, que se você irá familiarizar-se, pois ele é usado nos models de banco de dados do Django.
Por exemplo, considere um formulário usado para implementar a funcionalidade “contact me” num Web site pessoal:
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField()
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
Um formulário é composto de objetos Field. Neste caso, nosso formulário tem quatro campos: subject, message, sender e cc_myself. CharField, EmailField e BooleandField são somente três dos tipos tipos de campos disponíveis; uma lista completa pode ser encontrada em Campos de formulário.
Se seu formulário será usado para adicionar ou editar um model do Django diretamente, você pode usar um ModelForm para evitar duplicações de suas descrições de model.
O padrão para processar um formulário num view parece com isso:
def contact(request):
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # Um form com os dados de POST
if form.is_valid(): # All validation rules pass
# Processa os dados no form.cleaned_data
# ...
return HttpResponseRedirect('/thanks/') # Redireciona depois do POST
else:
form = ContactForm() # Um formulário vazio
return render_to_response('contact.html', {
'form': form,
})
Existem três caminhos de código aqui:
A distinção entre formulários bound e unbound é importante. Um formulário unbound não tem qualquer dado associado a ele; quando o formlário for renderizado para o usuário, ele estará vazio ou conterá valores padrão. Um fomrulário bound possui dados submetidos, e por isso pode ser usado para dizer se os dados são válidos. Se um formulário bound e inválido for renderizado ele pode incluír mensagens de erros, dizendo ao usuário onde ele errou.
Veja Bound e unbound formulários para mais informações sobre diferenças entre formulários bound e unbound.
Para ver como manipular upload de arquivos com seu formulário veja Vinculando arquivos enviados a um formulário para mais informações.
Uma vez que is_valid() retorne True, você pode processar a submissão do formulário sabendo que ela está em conformidade com as regras de validação definidas por seu formulário. Embora você possa acessar request.POST diretamente deste ponto, é melhor acessar form.cleaned_data. Estes dados não serão somente válidos, mas estarão convertidos em tipos relevantes do Python. No exemplo acima, cc_myself será um valor booleano. Da mesma forma, campos como IntegerField e FloatField serão convertidos para int e float do Python respectivamente.
Extendendo o exemplo acima, aqui temos como os dados do formulário podem ser processados:
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)
from django.core.mail import send_mail
send_mail(subject, message, sender, recipients)
return HttpResponseRedirect('/thanks/') # Redirect after POST
Para saber mais sobre como enviar e-mail do Django, veja Sending e-mail.
O Forms é projetados para trabalhar com a linguagem de templates do Django. No exemplo acima, nós passamos nossa instância do ContactForm para o template usando a variável de contexto form. Aqui temos um exemplo simples de template:
<form action="/contact/" method="POST"> {{ form.as_p }} <input type="submit" value="Submit" /> </form>
O form somente mostra seus próprios campos; ele não fornece tags <form> e o botão submit.
O forms.as_p mostrará o formulário com cada campo e sua respectiva label envolvidos por um parágrafo. Aqui temos uma saída para nosso template de exemplo:
<form action="/contact/" method="POST">
<p><label for="id_subject">Subject:</label>
<input id="id_subject" type="text" name="subject" maxlength="100" /></p>
<p><label for="id_message">Message:</label>
<input type="text" name="message" id="id_message" /></p>
<p><label for="id_sender">Sender:</label>
<input type="text" name="sender" id="id_sender" /></p>
<p><label for="id_cc_myself">Cc myself:</label>
<input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>
<input type="submit" value="Submit" />
</form>
Note que cada campo de formulário tem um atributo ID setado para id_<field-name>, que é referenciado por uma tag label. Isto é importante para assegurar que os formulários sejam acessíveis para tecnologias assistivas como leitores de tela. Você também pode customizar a forma em que as labels e ids são gerados.
Você pode também usar forms.as_table para gerar saídas como linhas de tabela. (você precisará fornecer suas próprias tags <table>) e forms.as_ul para mostrar em items de lista.
Se o HTML padrão gerado não é de seu gosto, você pode personalizar completamente a forma como o formulário é apresentado usando a linguagem de template do Django. Extendendo o exemplo acima:
<form action="/contact/" method="POST">
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="id_subject">E-mail subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="id_message">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="id_sender">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="id_cc_myself">CC yourself?</label>
{{ form.cc_myself }}
</div>
<p><input type="submit" value="Send message" /></p>
</form>
Cada campo de formulário nomeado pode ser mostrado ao template usando {{ form.nome_do_campo }}, que produzirá o HTML necessário para mostrar o widget de formulário. Usando {{ form.nome_do_campo.errors }} mostra uma lista de erros de formulário, renderizado como uma lista não ordenada. Ele pode parecer com isso:
<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:: A lista tem uma classe CSS errorlist para permitir que você mude sua aparência. Se você desejar personalizar a exibição dos erros, você pode fazê-lo iterando sobre eles:
{% if form.subject.errors %}
<ol>
{% for error in form.subject.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}
Se você estiver usando o mesmo HTML para cada um dos seus campos de formulário, você pode reduzir a duplicidade de código iterando sobre os campos usando um loop {% for %}:
<form action="/contact/" method="POST">
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Send message" /></p>
</form>
Dentro deste loop, {{ field }} é uma instância de :class`BoundField`. O BoundField também tem os seguintes atributos, que podem ser úteis nos seus templates:
Se seu site usa a mesma lógica de renderização para formulários em vários lugares, você pode reduzir a duplicidade utilizando um loop de formulário num template autônomo e usando a tag include para reusá-lo noutros templates:
<form action="/contact/" method="POST">
{% include "form_snippet.html" %}
<p><input type="submit" value="Send message" /></p>
</form>
# No form_snippet.html:
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
</div>
{% endfor %}
Se o objeto form passado a um template tem um nome diferente dentro do contexto, você pode criar um alias usando a tag with:
<form action="/comments/add/" method="POST">
{% with comment_form as form %}
{% include "form_snippet.html" %}
{% endwith %}
<p><input type="submit" value="Submit comment" /></p>
</form>
Se você se pegar fazendo isso frequentemente, você pode considerar criar uma inclusion tag personalizada.
Dec 26, 2011