Salve salve Pythonista!
Ou seria Djangista? Péssimo, esquece…
Hoje vamos aprender a desenvolver Formulários web incríveis utilizando Django Forms!
Esse post faz parte do contexto da Série Django aqui da Python Academy!
Já se liga nos outros posts:
Django: Introdução ao framework
Django: A Camada Model
Django: A Camada View
Django: A Camada Template
Vá Direto ao Assunto…
- Processamento de Formulários HTML no Django
- Criando seu primeiro
Form
- Criando Forms com
ModelForm
- Juntando tudo
- BÔNUS: Alterando o comportamento padrão com
Widgets
Mas primeiro...
Eu disponibilizei gratuitamente a aula introdutória do nosso Curso de Django - que é parte integrante do curso Jornada Python, aqui da Python Academy - e acho que você pode aprender bastante com ela!
Nesse vídeo você vai aprender sobre:
- Desenvolvimento Frontend vs Backend
- Arquitetura do Django
- Por que aprender Django
- O mercado para o Desenvolvedor Django
- O salário do Dev Django trabalhando para fora
- Quais empresas utilizam o Django
É só clicar na imagem abaixo para assistir o vídeo!
Processamento de Formulários HTML no Django
O tratamento de formulários é uma tarefa que pode ser bem complexa.
Considere um formulário com diversos campos e diversas regras de validação: seu tratamento não é mais um processo simples.
Os Forms do Django são formas de descrever os elementos <form>...</form>
das páginas HTML, simplificando e automatizando o processo de validação.
O Django trata três partes distintas dos formulários:
- Preparação dos dados tornando-os prontos para renderização
- Criação de formulários HTML para os dados
- Recepção e processamento dos formulários enviados ao servidor
Basicamente, queremos uma forma de renderizar em nosso template o código HTML:
1
2
3
4
5
<form action="/insere-funcionario/" method="post">
<label for="nome">Your name: </label>
<input id="nome" type="text" name="nome" value="">
<input type="submit" value="Enviar">
</form>
Que, ao ser submetido ao servidor, tenha seus campos de entrada validados e inseridos no banco de dados.
No centro desse sistema de formulários do Django está a classe Form
.
Nela, nós deescrevemos os campos que estarão disponíveis no formulário HTML e os métodos de validação.
Para o formulário acima, podemos descrevê-lo da seguinte forma.
1
2
3
4
5
6
7
from django import forms
class InsereFuncionarioForm(forms.Form):
nome = forms.CharField(
label='Nome do Funcionário',
max_length=100
)
Nesse formulário:
- Utilizamos a classe
forms.CharField
para descrever um campo de texto. - O parâmetro
label
descreve um rótulo para esse campo. -
max_length
decreve o tamanho máximo que esse input pode receber (100 caracteres, no caso).
Existem diversos tipos de campos possíveis de serem utilizados, por exemplo:
-
BooleanField
: mapeia um campo booleano, resultando em umcheckbox
no HTML final. -
DecimalField
: mapeia um campo decimal, resultando em um<input type='number' ...>
no HTML final. -
EmailField
: mapeia um campo de email, resultando em um<input type='email' ...>
no HTML final.
Veja os diversos tipos de campos disponíveis acessando aqui
A classe forms.Form
possui um método muito importante, chamado is_valid()
.
Quando um formulário é submetido ao servidor, esse é um dos métodos que irá realizar a validação dos campos do formulário.
Se tudo estiver OK, ele colocará os dados do formulário no atributo cleaned_data
(que pode ser acessado por você posteriormente para pegar alguma informação - como o nome que foi inserido pelo usuário no campo <input name='nome'>
).
Como o processo de validação do Django é bem complexo e para não prolongar muito o post, acesse a documentação aqui para saber mais.
Está curtindo esse conteúdo?
Que tal receber 30 dias de conteúdo direto na sua Caixa de Entrada?
Criando seu primeiro Form
Vamos ver agora um exemplo mais complexo com um formulário de inserção de uma entidade exemplo Funcionário, com todos os campos.
Primeiro, vamos criar a seguinte modelagem da entidade Funcionario
no arquivo models.py
de sua aplicação:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from django.db import models
class Funcionario(models.Model):
nome = models.CharField(
max_length=255,
null=False,
blank=False
)
sobrenome = models.CharField(
max_length=255,
null=False,
blank=False
)
cpf = models.CharField(
max_length=14,
null=False,
blank=False
)
tempo_de_servico = models.IntegerField(
default=0,
null=False,
blank=False
)
remuneracao = models.DecimalField(
max_digits=8,
decimal_places=2,
null=False,
blank=False
)
Em seguida, vamos criar um arquivo forms.py
para guardar os formulários de nossa aplicação. Crie-o no mesmo app
que criou o modelo Funcionário
.
Dessa forma, e consultando a documentação dos possíveis campos do nosso formulário, nós podemos descrever um formulário de inserção da seguinte forma:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from django import forms
class InsereFuncionarioForm(forms.Form)
nome = forms.CharField(
required=True,
max_length=255
)
sobrenome = forms.CharField(
required=True,
max_length=255
)
cpf = forms.CharField(
required=True,
max_length=14
)
tempo_de_servico = forms.IntegerField(
required=True
)
remuneracao = forms.DecimalField(
required=True
)
Affff, o Model e o Form são quase iguais… Terei que reescrever os campos toda vez?
Claro que não, jovem! Pra isso o Django criou o incrível ModelForm
!
Ah, antes de seguir! Está curtindo esse conteúdo? Que tal levá-lo pra onde quiser?
Então já baixe nosso ebook GRÁTIS de Desenvolvimento Web com Python e Django!
Ebook GRÁTIS
DESENVOLVIMENTO WEB COM PYTHON E DJANGO
Conteúdo:
- Veja como modelar sua aplicação
- Utilize a robusta API de Acesso a Dados do Django
- Aprenda sobre Class Based Views
- Construa Middlewares próprios
- Desenvolva filtros e tags customizados para criar lindos templates
Criando Forms com ModelForm
Com o ModelForm
nós descrevemos os campos que queremos (atributo fields
) e/ou os campos que não queremos (atributo exclude
).
Para isso, utilizamos a classe interna Meta
para incluirmos esses metadados na nossa classe.
Metadado (no caso do Model e do Form
) é tudo aquilo que não será transformado em campo, como model
, fields
, ordering
etc (mais sobre Meta
options)
Nosso ModelForm
, pode ser descrito da seguinte forma:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from django import forms
class InsereFuncionarioForm(forms.ModelForm):
class Meta:
# Modelo base
model = Funcionario
# Campos que estarão no form
fields = [
'nome',
'sobrenome',
'cpf',
'remuneracao'
]
# Campos que não estarão no form
exclude = [
'tempo_de_servico'
]
Viu que simples!
Podemos utilizar apenas o campo fields
, apenas o campo exclude
ou os dois juntos.
Mesmo utilizando os atributos fields
e exclude
, ainda podemos adicionar outros campos, independente dos campos do modelo Funcionário
.
O resultado será um formulário com todos os campos presentes no fields
, menos os campos do exclude
mais os campos adicionados.
Ficou confuso? Então vamos ver o exemplo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from django import forms
class InsereFuncionarioForm(forms.ModelForm)
chefe = forms.BooleanField(
label='Chefe?',
required=True,
)
biografia = forms.CharField(
label='Biografia',
required=False,
widget=forms.TextArea
)
class Meta:
# Modelo base
model = Funcionario
# Campos que estarão no form
fields = [
'nome',
'sobrenome',
'cpf',
'remuneracao'
]
# Campos que não estarão no form
exclude = [
'tempo_de_servico'
]
Isso vai gerar um formulário com:
- Todos os campos contidos em
fields
menos os campos contidos emexclude
- O campo
chefe
, renderizado como um checkbox (<input type='checkbox' name='chefe' ...>
) - Uma área de texto para biografia (
<textarea name='biografia' ...></textarea>
)
Mas como biografia
será um <textarea .../>
se ele é um CharField
?
Calma lá…. Você vai descobrir na seção BÔNUS!
Ei, você aí! Quer se sentir realmente capaz ao desenvolver Aplicações Web com Django? Então clique no link abaixo e dê o próximo passo agora mesmo!
A Jornada Django foi pensada em quem já sabe Python e quer dar o próximo passo. Aqui você vai dominar o Desenvolvimento Web com o poderoso Django.
(Será redirecionado para jornadadjango.com.br)
Juntando tudo
Poderíamos criar uma CreateView
para renderizar esse Form
da seguinte forma:
1
2
3
4
5
6
7
8
from django.views.generic import CreateView
from django.urls import reverse_lazy
class FuncionarioCreateView(CreateView):
template_name = "website/cria.html"
model = Funcionario
form_class = InsereFuncionarioForm
success_url = reverse_lazy("website:lista_funcionarios")
Nela:
-
template_name
: Aponta para o HTML base para renderização do form. -
model
: O modelo associado à essaView
. -
form_class
:Form
que será disponibilizado no template, definido ali em cima. -
success_url
: URL para redirecionar o usuário, em caso de sucesso.
Já para o template HTML, temos duas estratégias:
- Deixar que o Django renderize tudo: aqui você não tem muito controle de como será o layout do resultado final.
- Construir o código HTML: eu prefiro essa opção para construir algo mais bonito no final.
Vamos ao resultado de ambas alternativas.
Na primeira, o código HTML poderia ser assim:
1
2
3
4
5
6
7
8
9
10
11
<form method="post">
<!-- Não se esqueça dessa tag -->
{% csrf_token %}
<hr>
<div class="text-right">
<a href="{% url 'website:lista_funcionarios' %}" class="btn btn-outline-primary">Voltar</a>
<button class="btn btn-primary">Enviar</button>
</div>
</form>
O que resultaria no seguinte HTML, após renderizado:
Pouco código, contudo…
Meio “feio” pra mostrar pra um cliente, não concorda?
Já utilizando a segunda estratégia, poderíamos construir parte do HTML resultante, tendo um controle maior sobre o layout.
Para isso, gosto de utilizar a biblioteca Django Widget Tweaks.
Ela possibilita adicionar classes CSS ao campos do formulário (coisa que o Django, por padrão, não permite).
Dessa forma, e usando um pouco de Bootstrap, podemos construir nosso formulário da seguinte forma:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!-- Carrega as tags do Django Widget Tweaks para utilização -->
{% load widget_tweaks %}
<form method="post">
<!-- Não se esqueça dessa tag -->
{% csrf_token %}
<!-- Nome -->
<div class="input-group mb-3">
<div class="input-group-prepend"><span class="input-group-text">Nome</span></div>
{% render_field form.nome class+="form-control" %}
</div>
<!-- Sobrenome -->
<div class="input-group mb-3">
<div class="input-group-prepend"><span class="input-group-text">Sobrenome</span></div>
{% render_field form.sobrenome class+="form-control" %}
</div>
<!-- CPF -->
<div class="input-group mb-3">
<div class="input-group-prepend"><span class="input-group-text">CPF</span></div>
{% render_field form.cpf class+="form-control" %}
</div>
<!-- Tempo de Serviço -->
<div class="input-group mb-3">
<div class="input-group-prepend"><span class="input-group-text">Tempo de Serviço</span></div>
{% render_field form.tempo_de_servico class+="form-control" %}
</div>
<!-- Remuneração -->
<div class="input-group mb-3">
<div class="input-group-prepend"><span class="input-group-text">Remuneração</span></div>
{% render_field form.remuneracao class+="form-control" %}
</div>
<!-- Chefe -->
<div class="input-group mb-3">
<div class="input-group-prepend"><span class="input-group-text">Chefe?</span></div>
{% render_field form.chefe class+="form-control" %}
</div>
<!-- Biografia -->
<div class="input-group mb-3">
<div class="input-group-prepend"><span class="input-group-text">Biografia</span></div>
{% render_field form.biografia class+="form-control" %}
</div>
<hr>
<div class="text-right">
<a href="{% url 'website:lista_funcionarios' %}" class="btn btn-outline-primary">Voltar</a>
<button class="btn btn-primary">Enviar</button>
</div>
</form>
O que resultaria na seguinte tela:
Mais bonito pra colocar no portifólio, né?
BÔNUS: Alterando o comportamento padrão com Widgets
Assim como é possível definir atributos nos modelos, os campos do formulário também são customizáveis.
Veja que o campo biografia
do nosso InsereFuncionarioForm
é do tipo CharField
, portanto deveria ser renderizado como um campo <input type='text' ...>'
.
Contudo, eu modifiquei o campo setando o atributo widget
com forms.TextArea
, assim:
1
2
3
4
5
biografia = forms.CharField(
label='Biografia',
required=False,
widget=forms.TextArea
)
Assim, ele não mais será um simples input, mas será renderizado como um <textarea></textarea>
no nosso template!
O Django possui diversos tipos de Widgets
disponíveis, por exemplo:
- Podemos esconder um campo
CharField
com o widgetHiddenInput
. - Podemos transformar um campo
CharField
para ser renderizado como campo de senha com o widgetPasswordInput
. - Podemos usar o widget
FileInput
para fazer um campo para upload de arquivos!
As possibilidades são infinitas!
Conclusão
Nesse post, vimos o poder dos Django Forms e sua flexibilidade!
Vimos como podemos construí-lo a partir da modelagem do nosso sistema através dos ModelForms
.
Também vimos o quão simples é alterar o comportamento de um campo do formulário através dos Widgets
.
É isso por hoje dev! Nos vemos na próxima!