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?
![](/assets/img/desenho-30-dias-de-python.png)
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
![Capa Ebook Desenvolvimento Web com Python e Django](/assets/ebooks/desenvolvimento-web-com-python-e-django/ebook-cover.webp)
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!
![Jornada Django](/assets/img/jornada-django-thumb-post.webp)
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.
![Vinícius Ramos](/assets/img/foto-vinicius.png)
(Será redirecionado para jornadadjango.com.br)
![Check](/assets/img/check.webp)
![Check](/assets/img/check.webp)
![Check](/assets/img/check.webp)
![Check](/assets/img/jornada-python-v4/logo-html-pricing.png)
![Check](/assets/img/jornada-python-v4/logo-css-pricing.png)
![Check](/assets/img/jornada-python-v4/logo-js-pricing.png)
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!