[DJANGO][FORMULÁRIOS] Como validar um formulário.
E aí pessoal, tudo bem?
Venho mais uma vez demonstrar alguns conhecimentos obtidos ao longo do tempo que estudo o Django.
Dessa vez, vamos falar sobre validação. Eu sempre tive a ideia de que um formulário deve ser algo visual para o usuário, que o faça sentir se deu certo ou errado aquilo que esteja tentando fazer. A parte visual conta muito nesse processo.
Vamos começar diretamente no arquivo views.py e forms.py.
Eu sempre tento criar um padrão para os formulários; eu prefiro validar algumas coisas neles. Pode ser considerado um método ruim? Não sei, nunca ouvi falar sobre não fazer esse tipo de validação, como as validações de usuário.
Eu crio as views utilizando CBV (Class-Based Views), o que facilita algumas validações. Há pessoas que não gostam das class-based views, mas eu não vejo problemas.
Modelo simples para criação e autenticação de usuários
Também é possível adicionar envios de emails com links únicos, isso ficará para um próximo post.
Corrijam apenas os erros de português, lembrando que isso é um markdown.
class SignInView(FormView):
template_name = 'pages/authentication/signin.html'
form_class = SignInForm
success_url = '/'
def form_valid(self, form):
email, password = form.cleaned_data.values()
user = authenticate(self.request, email=email, password=password)
try:
if user is not None:
login(self.request, user)
return super().form_valid(form)
else:
return super().form_invalid(form)
except Account.DoesNotExist:
return super().form_invalid(form)
class SignUpView(FormView):
template_name = 'pages/authentication/signup.html'
form_class = SignUpForm
success_url = '/entrar/'
def form_valid(self, form):
(first_name,
last_name,
username,
email,
password,
re_password) = form.cleaned_data.values()
if password != re_password:
return super().form_invalid(form)
Account.objects.create_user(
first_name=first_name,
last_name=last_name,
username=username,
email=email,
password=password
)
return super().form_valid(form)
Após a criação das Views primeiramente crio um DefaultForm para atualizar os estilos, utilizando TAILWINDCSS, dentro do meu DefaultForm, crio uma validação onde verifica se o field tem um erro e se tiver atualiza seu estilo.
Essas são as validações padrões que uso em meus projetos.
import re
from django import forms
from .models import Account
class DefaultForm(forms.Form):
def __init__(self, *args, **kwargs):
super(DefaultForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'w-80 rounded-md border-[0.0125rem] py-2.5 indent-2 text-xs placeholder:text-xs dark:border-none'
field.widget.attrs['placeholder'] = field.label
if self.errors.get(field_name):
field.widget.attrs['class'] += ' ring-[0.0625rem] ring-red-500 focus:outline-red-500'
class SignInForm(DefaultForm):
email = forms.EmailField(label='E-mail')
password = forms.CharField(label='Senha', widget=forms.PasswordInput)
def clean_email(self):
email = self.cleaned_data.get('email')
if not Account.objects.filter(email=email).exists():
self.add_error('email', 'Este e-mail não está cadastrado.')
return email
def clean_password(self):
email = self.cleaned_data.get('email')
password = self.cleaned_data.get('password')
if Account.objects.filter(email=email).exists():
user = Account.objects.get(email=email)
if not user.check_password(password):
self.add_error('password', 'Senha incorreta.')
return password
class SignUpForm(DefaultForm):
first_name = forms.CharField(label='Nome', max_length=100)
last_name = forms.CharField(label='Sobrenome', max_length=100)
username = forms.CharField(label='Nome de Usuário', max_length=100)
email = forms.EmailField(label='E-mail')
password = forms.CharField(label='Senha', widget=forms.PasswordInput)
re_password = forms.CharField(
label='Confirmação de Senha', widget=forms.PasswordInput)
def clean_username(self):
username = self.cleaned_data.get('username')
if Account.objects.filter(username=username).exists():
self.add_error('username', 'Este nome de usuário já está em uso.')
return username
def clean_email(self):
email = self.cleaned_data.get('email')
if Account.objects.filter(email=email).exists():
self.add_error('email', 'Este e-mail já está em uso.')
return email
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
re_password = cleaned_data.get('re_password')
if password and re_password and password != re_password:
self.add_error('re_password', 'As senhas não coincidem.')
if password:
if not re.match(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$', password):
self.add_error(
'password', 'A senha deve conter pelo menos 8 caracteres'
'incluindo letras maiúsculas, minúsculas,'
' números e caracteres especiais.'
)
return cleaned_data
<form action="{% url 'signup' %}" method="POST">
<div class="flex flex-col gap-2">
{% csrf_token %}
{% for field in form %}
<label for="{{ field.id_for_label }}" class="flex flex-col">
{{ field }}
{% if field.errors %}
<ul class="text-xs text-red-500 mt-1 max-w-[20rem]">
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</label>
{% endfor %}
</div>
<button type="submit" class="my-2 w-full rounded-md bg-indigo-400 py-2.5 text-sm text-white hover:bg-indigo-500">Entrar</button>
</form>
At.te
Igor Lopes Ribeiro.
Email para contato