Validação de Formulários no Django: Componente Forms com Hooks e Limpeza de Dados

Ao construir formulários no Django, o componente Forms oferece uma maneira robusta de validar dados de entrada. Neste exemplo, implementaremos um formulário de registro com validação para nome de usuário, senha, confirmação de senha e e-mail, explorando conceitos como error_messages, label, required, invalid, funções de gancho (hooks) locais e globais, além de atributos como forms_obj.cleaned_data e forms_obj.errors.

Configuração de URLs

Defina as rotas no arquivo urls.py para acessar as views.


from django.urls import path
from django.contrib import admin
from . import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('cadastro/', views.cadastro),
    path('home/', views.home),
]

Definição do Formulário e Views

No views.py, crie uma classe de formulário com validações e funções de gancho, além das views para manipulação.


from django import forms
from django.http import HttpResponse
from django.shortcuts import render

class FormCadastro(forms.Form):
    usuario = forms.CharField(
        max_length=8,
        min_length=3,
        label='Usuário',
        error_messages={
            'max_length': 'O usuário deve ter no máximo 8 caracteres.',
            'min_length': 'O usuário deve ter no mínimo 3 caracteres.',
            'required': 'Campo obrigatório.',
        }
    )
    senha = forms.CharField(
        max_length=8,
        min_length=3,
        label='Senha',
        error_messages={
            'max_length': 'A senha deve ter no máximo 8 caracteres.',
            'min_length': 'A senha deve ter no mínimo 3 caracteres.',
            'required': 'A senha não pode ser vazia.',
        }
    )
    confirmar_senha = forms.CharField(
        max_length=8,
        min_length=3,
        label='Confirmar Senha',
        error_messages={
            'max_length': 'A confirmação deve ter no máximo 8 caracteres.',
            'min_length': 'A confirmação deve ter no mínimo 3 caracteres.',
            'required': 'Confirme a senha.',
        }
    )
    email = forms.EmailField(
        label='E-mail',
        error_messages={
            'required': 'O e-mail é obrigatório.',
            'invalid': 'Formato de e-mail inválido.',
        }
    )

    # Gancho local para validar o campo usuario
    def clean_usuario(self):
        valor = self.cleaned_data.get('usuario')
        if 'abc' in valor.lower():
            self.add_error('usuario', 'O usuário não pode conter "abc".')
        return valor

    # Gancho global para verificar correspondência de senhas
    def clean(self):
        dados = super().clean()
        senha = dados.get('senha')
        confirmacao = dados.get('confirmar_senha')
        if senha and confirmacao and senha != confirmacao:
            self.add_error('confirmar_senha', 'As senhas não coincidem.')
        return dados

def home(request):
    form_obj = FormCadastro()
    if request.method == 'POST':
        form_obj = FormCadastro(request.POST)
        if form_obj.is_valid():
            # Dados válidos estão em form_obj.cleaned_data
            print(form_obj.cleaned_data)
            return HttpResponse('Validação bem-sucedida!')
        else:
            # Erros podem ser acessados via form_obj.errors
            print(form_obj.errors)

    # Usar locals() para passar variáveis ao template, mas evitando dependência excessiva
    contexto = {'form_obj': form_obj}
    return render(request, 'home.html', contexto)

Template para Exibição

No templtae HTML, itere sobre os campos do formulário para exibir labels, inputs e mensagens de erro.


<form method="post" novalidate>
    {% csrf_token %}
    {% for campo in form_obj %}
        <div>
            <label>{{ campo.label }}</label>
            {{ campo }}
            {% if campo.errors %}
                <span class="erro">{{ campo.errors.0 }}</span>
            {% endif %}
        </div>
    {% endfor %}
    <button type="submit">Enviar</button>
</form>

Tags: Django forms form-validation cleaned-data error-messages

Publicado em 6-18 20:30