Formulários

Os formulários em Django são uma ferramenta poderosa para lidar com entrada de dados, validação, e interação entre usuários e o sistema. O Django oferece duas abordagens principais para trabalhar com formulários:

  1. Formulários Manuais (forms.Form): Usados quando você quer criar formulários personalizados sem vinculação direta a modelos.

  2. Formulários Baseados em Modelos (forms.ModelForm): Usados para criar formulários automaticamente a partir de um modelo, vinculando os campos do formulário aos campos do modelo correspondente.

Todo formulário tem por padrão a sua ação para "/" nenhum lugar (localhost:8000/), para mudar isso adicione um action="/pagina"

Get e Post são dois métodos de requisições para servidores, onde Get é usado para obter dados, mas pode ser usado para enviar (não é recomendado por padrão) e Post para enviar dados. Para definir o método: <form action="/" method="POST"> Para recuperar os dados enviados: request.POST['nome_usuario']

CSRF é a sigla para Cross-Site Request Forgery, que em português significa falsificação de solicitação entre sites.O django nos protege desse tipo de ataque gerando um token para cada formulário, ou seja, só quem pode enviar formulários para nossa aplicação é a nossa propria aplicação, por isso no inicio de todo o formulário deve-se colocar a tag {%csrf_token%}

Validação dos Dados Quando o método is_valid() é chamado, o Django verifica os valores enviados para cada campo no formulário com base nas regras definidas (como required, max_length, etc.). Se todos os campos forem válidos:

  • O atributo cleaned_data é preenchido com os dados do formulário, já limpos e validados.
  • Os valores dos campos podem ser acessados como um dicionário em form.cleaned_data.

No Django, o atributo form.cleaned_data contém os dados do formulário que passaram pela validação definida no próprio formulário. Esses dados são acessíveis apenas após o método is_valid() retornar True, indicando que todos os campos do formulário foram preenchidos corretamente de acordo com as regras definidas. form.cleaned_data é uma maneira segura e validada de acessar os dados de um formulário após passar por todas as verificações e regras definidas no Django. Quando o formulário é inválido, o Django preenche o atributo form.errors com os erros.

Diferença entre request.POST e form.cleaned_data
Aspecto request.POST form.cleaned_data
Dados brutos Contém os dados enviados pelo cliente (formulário HTML). Contém os dados validados e limpos.
Validação Nenhuma validação automática. Apenas campos válidos e limpos aparecem.
Segurança Pode conter valores maliciosos ou ausentes. Apenas valores validados aparecem.
Os principais tipos de campos disponíveis para formulários em Django:
Tipo de Campo Django Descrição Parâmetros Principais Equivalente HTML
CharField Campo para entrada de texto curto. max_length, min_length, required, widget, label, initial, help_text <input type="text">
EmailField Campo para validar e armazenar endereços de e-mail. max_length, required, widget, label, initial, help_text <input type="email">
IntegerField Campo para números inteiros. min_value, max_value, required, label, initial, help_text <input type="number">
DecimalField Campo para números decimais. max_digits, decimal_places, min_value, max_value, required, label <input type="number">
FloatField Campo para números de ponto flutuante. min_value, max_value, required, label, initial, help_text <input type="number">
BooleanField Campo para valores booleanos (True/False). required, label, initial, help_text <input type="checkbox">
ChoiceField Campo para seleção de uma opção em uma lista. choices, required, widget, label, initial, help_text <select>
MultipleChoiceField Campo para selecionar várias opções em uma lista. choices, required, widget, label, initial, help_text <select multiple>
DateField Campo para entrada de data. input_formats, widget, label, initial, help_text <input type="date">
DateTimeField Campo para entrada de data e hora. input_formats, widget, label, initial, help_text <input type="datetime-local">
TimeField Campo para entrada de hora. input_formats, widget, label, initial, help_text <input type="time">
URLField Campo para validar e armazenar URLs. max_length, required, widget, label, initial, help_text <input type="url">
SlugField Campo para texto curto sem espaços (slugs). max_length, required, label, initial, help_text <input type="text">
ImageField Campo para upload de imagens. required, label, initial, help_text, widget, validators <input type="file">
FileField Campo para upload de arquivos. required, label, initial, help_text, widget, validators <input type="file">
Textarea (via widget) Campo de texto longo (múltiplas linhas). required, label, initial, help_text, widget=forms.Textarea <textarea>
PasswordInput (via widget) Campo para entrada de senhas (oculta os caracteres). required, label, initial, help_text, widget=forms.PasswordInput <input type="password">

Widgets no Django são classes responsáveis por definir como um campo de formulário será exibido no HTML. Não é um campo, só a forma de exibir o campo. Só afeta o HTML gerado no template.

O que fazem os Widgets:
O que ele controla Exemplo
Tipo de input HTML gerado <input>, <textarea>, <select>, etc
Classes CSS extras class="form-control"
Atributos extras placeholder, maxlength, etc
Renderização de HTML customizado Formatação personalizada do campo

Para criar formulários em django:

  1. Criar um arquivo forms.py dentro de seu app
  2. Criar uma classe que herda de forms.Form ou forms.ModelForm
  3. Criar os campos dentro da classe
  4. Criar um formulário em seu template

 

| Exemplo formulário forms.Form

forms.py
from django import forms

class AvaliacaoForm(forms.Form):

    # O atributo required padrão é True
    nome_usuario = forms.CharField(
        label="Seu nome ",
        max_length=100,

        # Personalizando as mensagens de erro
        error_messages={
            'required': 'Campo obrigatório',
            'max_length': 'Máximo de 100 caracteres',
        },)

    descricao = forms.CharField(
        label="O que achou do Livro",

        # Define o tipo como texto
        widget=forms.Textarea,
        max_length=200,
    )

    avaliacao = forms.IntegerField(
        label="Nota",
        min_value=1,
        max_value=5,
    )

Se o label não for definido o django usará o nome do campos. Ex.: nome_usuario ficará Nome Usuario.

avaliacao.html
<body>

  <form action="{% url 'avaliacao' %}" method="POST">
    {% csrf_token %}

    <!-- loop para todos os campos definidos em meu formulário-->
    {% for field in form %}
      <div class="form-control {%if field.errors%} errors {% endif %}">

        <!-- Exibe o label do campo -->
        {{field.label_tag}}

        <!-- Exibe o campo -->
        {{field}}

        <!-- Se houver um texto de ajuda (ex.: Deve conter uma letra maiúscula) exibe-o -->
        {% if field.help_text %}
            <p class="help-text">{{ field.help_text }}</p>
        {% endif %}

        <!-- Se houver erro, exibe abaixo do campo a mensagem de erro-->
        {{field.errors}}

      </div>
    {% endfor %}

    <button type="submit">Enviar</button>

  </form>
</body>

Ao invés de usar: <form action="/avaliacao" method="POST">, usar: {% url 'avaliacao' %} garante que, se a URL mudar no futuro, o template continuará funcionando.

No template posso personalizar uma classe de erros no css, caso haja algum erro. Se houver erros será renderizada assim: <div class="form-control  errors ">, Caso deseje exibir todo o fomulário sem personalizar use o formulário completo, nesse caso: {{ form }}. Quando formulario completo é passado (pela view), ele já inclui a renderização dos campos do formulário e uma lista com Mensagens de erro automaticamente atribuídas aos campos inválidos.

views.py
from django.shortcuts import render
from .forms import AvaliacaoForm

def avaliacao_view(request):
    if request.method == 'POST':
        # Instancia o formulário com os dados enviados via POST
        form = AvaliacaoForm(request.POST)

        if form.is_valid():
            # Obtém os dados validados do formulário
            nome_usuario = form.cleaned_data['nome_usuario']
            descricao = form.cleaned_data['descricao']
            avaliacao = form.cleaned_data['avaliacao']

            # Aqui você pode processar os dados, como salvar no banco, enviar email, etc.
            print(f"Nome: {nome_usuario}, Descrição: {descricao}, Avaliação: {avaliacao}")

            # Retorna uma mensagem de sucesso
            return render(request, 'meu_app/sucesso.html', {'nome_usuario': nome_usuario})
    else:
        # Se for uma requisição GET, cria um formulário vazio
        form = AvaliacaoForm()

    # Renderiza a página com o formulário vazio ou se is_valid() for falso retorna com os erros
    return render(request, 'meu_app/avaliacao.html', {'form': form})

O método is_valid() valida os dados com base nas regras definidas no formulário (max_length, min_value, etc.). As validações em formularios (nas views) são extremamente necessárias para consistência de dados, já que as validações em html podem ser burladas usando navegador (ferrameta de desenvolvedor).

sucesso.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sucesso</title>
</head>
<body>
    <h1>Obrigado, {{ nome_usuario }}!</h1>
    <p>Sua avaliação foi enviada com sucesso.</p>
</body>
</html>
urls.py
from django.urls import path
from . import views

urlpatterns = [
    # URL para a avaliação
    path('avaliacao/', views.avaliacao_view, name='avaliacao'),
]

Urls.py do meu_app.

| Exemplo formulário forms.ModelForm

models.py
from django.db import models

class Avaliacao(models.Model):
    nome_usuario = models.CharField(max_length=20)
    descricao = models.TextField()
    avaliacao = models.IntegerField()

    def __str__(self):
        return self.nome_usuario

Não está sendo feita validação dos campos, pois já está sendo feita no forms.py.

forms.py
from django import forms
from .models import Avaliacao

class AvaliacaoForm(forms.ModelForm):

    # Configuro algumas propriedades extras com META
    class Meta:
        model = Avaliacao

        # O uso do __all__ serve para especificar que todos os meus campos serão incluídos no formulário (menos id)
        fields = "__all__"

        # Poderia ser uma lista com os campos especificos:
        # fields = ['name', 'age','last name', 'comments']

        # Poderia selecionar todos menos alguns
        # exclude = ['last name', 'comments']

        labels = {
            "nome_usuario ": "Seu Nome",
            "descricao": "Feedback",
            "Avaliacao": "Avaliação",
        }

        error_messages = {
            "nome_usuario ": {
                'required': 'Campo obrigatório',
                'max_length': 'Máximo de 100 caracteres',
            }
        }

        help_texts = {
            'email': 'Digite seu melhor email',
        }

Se não forem definidos os labels, os nomes serão criados com base no nome dos campos do banco de dados (models).

help_texts são as mensagens que acompanharão os campos.

views.py
from .forms import AvaliacaoForm
from django.http import HttpResponseRedirect

def avaliacao_view(request):
    if request.method == 'POST':
        
        # passo os dados inseridos no formulário para minha classe de tratamento criada em .forms
        form = AvaliacaoForm(request.POST)

        if form.is_valid():
            form.save()
            render(request, "meu_app/sucesso.html")
            # return HttpResponseRedirect("meu_app/sucesso.html")
    else:
        # Cria um formulario vazio para exibir quando a pagina é carregada ou redirecionada
        form = AvaliacaoForm()
    return render(request, "meu_app/avaliacao.html", {
        "form": form
    })

Em caso de desejar atualizar, o método save funcionará para atualização. Para atualização:
        # existing_data = Review.objects.get(pk=1) # form = ReviewForm(request.POST, instance=existing_data)

forms_metodos_especiais.py
from django import forms
from .models import Avaliacao

class AvaliacaoForm(forms.ModelForm):
    class Meta:
        model = Avaliacao
        fields = ['name', 'age','last name', 'comments']

        def clean_name(self):
            # Esse método é chamado automaticamente pelo Django para validar o campo "first_name"
            data = self.cleaned_data.get('first_name')
            # Aqui ele pega o valor já limpo (pre-processado) do campo "name". Esse valor vem do formulário preenchido pelo usuário. Exemplo: se o usuário digitou "John Doe", 'data' vai conter essa string.

            if 'John Doe' in data:
                # Se o valor do campo contém a string "John Doe", queremos bloquear.

                raise ValidationError(
                    # Levanta um erro de validação. Isso faz o form.is_valid() retornar False
                    # E a mensagem de erro vai aparecer ao lado do campo no formulário renderizado.

                    'Não digite John Doe no campo name',
                    # Mensagem de erro que será exibida.

                    code='invalid', # Código interno para o tipo de erro. Pode ser usado em mensagens customizadas ou tradução.

            return data
            # Se passou na validação, retorna o valor original do campo.
            # Esse valor vai para o form.cleaned_data['first_name']

# EXEMPLO 2, verificação cruzada (entre dois campos):
from django import forms
from django.core.exceptions import ValidationError


class RegisterForm(forms.Form):
    username = forms.CharField()
    password = forms.CharField(widget=forms.PasswordInput)
    password2 = forms.CharField(widget=forms.PasswordInput)

    def clean(self):
        # Chama a validação padrão do Django para pegar todos os campos
        cleaned_data = super().clean()

        # Pega os valores dos campos já limpos
        password = cleaned_data.get('password')
        password2 = cleaned_data.get('password2')

        # Validação cruzada: conferindo se as duas senhas são iguais
        if password and password2:
            if password != password2:
                # Se as senhas forem diferentes, levanta um erro de validação geral
                raise ValidationError('As senhas devem ser iguais.')

        # Sempre retorne os dados limpos
        return cleaned_data

No Django, esxitem metodos especiais para validação de campos, qualquer método que siga o padrão: def clean_<nome_do_campo>(self): ..., o Django procura automaticamente por métodos com o esse padrão. ele executa esse método durante a validação do formulário, ou seja, durante form.is_valid() ou form.full_clean(), antes de colocar o valor final no self.cleaned_data['nome_do_campo']. É uma validação específica para aquele campo dentro do formulário.

Usando a estrutura do exemplo acima usariamos uma classe View ao invés da função

forms_CBV
from django.views import View
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import AvaliacaoForm

class AvaliacaoView(View):
    # Método para requisições GET
    def get(self, request):
        form = AvaliacaoForm()  # Cria um formulário vazio
        return render(request, "meu_app/avaliacao.html", {"form": form})

    # Método para requisições POST
    def post(self, request):
        form = AvaliacaoForm(request.POST)  # Preenche o formulário com os dados enviados
        if form.is_valid():
            # Salva os dados no banco (se o formulário estiver configurado para isso)
            # Aqui seria o momento de manipular dados antes de salvar, se necessário
            form.save()
            return HttpResponseRedirect("/sucesso.html")  # Redireciona para a página de sucesso

        # Recarrega o formulário com os erros
        return render(request, "meu_app/avaliacao.html", {"form": form})
urls_CBV.py
from django.urls import path
from . import views

urlpatterns = [
     path("", views.AvaliacaoView.as_view()),
]

Exemplo de uma url para CBV acima


Formulário UserCreationForm

O UserCreationForm é um formulário pronto que o Django fornece para facilitar a criação de novos usuários com autenticação (login/senha) para a tabela padrão do Django. Ele já inclui: Campo de username, dois campos de senha (password1 e password2), valida se as senhas batem, e salva automaticamente um objeto User no banco

Obs.:  O {{ form.as_p }} é uma forma de renderizar o formulário como parágrafos (<p>) no template HTML.

Método Resultado
form.as_p Cada campo em um <p>
form.as_table Cada campo como uma linha de <table>
form.as_ul Cada campo como um item de <ul>

| Exemplo UserCreateForm

views.py
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm

def register(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('login')  # ou redireciona pra onde quiser
    else:
        form = UserCreationForm()

    return render(request, 'register.html', {'form': form})


# Caso queira personalizar pode extender a classe UserCreationForm
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django import forms

class CustomUserCreationForm(UserCreationForm):
    email = forms.EmailField(required=True)

    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']
register.html
<h2>Registrar</h2>
<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit">Registrar</button>
</form>

Formulário de Login e Autenticação

O AuthenticationForm é um formulário pronto do Django que valida o login de um usuário. Ele já vem com os campos: usernamepassword. Automaticamente valida: Se o usuário existe, se a senha está correta e se o usuário está ativo.

A função login() do Django serve para autenticar o usuário na sessão. Quando você chama essa função, ela:

  1. Cria uma sessão para o usuário no navegador (usando cookies).

  2. Salva o ID do usuário autenticado na sessão (request.session).

  3. Torna o usuário acessível através de request.user nas próximas requisições.

Existe também a classe User de django.contrib.auth.models, que serve para criar, gerenciar e autenticar usuários no seu site ou sistema. Essa classe é muito usada com modelos (models) ou no Shell. 

view_AuthenticationForm.py
from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.contrib.auth.forms import AuthenticationForm

def login_view(request):
    if request.method == "POST":
        # Cria um formulário de autenticação com os dados do POST e valida senha e usuário
        form = AuthenticationForm(data=request.POST)
        if form.is_valid():
            user = form.get_user() # Obtém o usuário autenticado
            login(request, user)  # Faz o login criando a sessão
            # poderia ser assim -> login(request, form.save()) #Faz o login do usuário após o registro
            return redirect('products:list')  # Redireciona após o login
    else:
        form = AuthenticationForm()
    return render(request, 'users/login.html', {'form': form})

| Exemplo de autenticação

login_formulario.html
{% if user.is_authenticated %}
    <button>Logout</button>
{% else %}
    <button>Logout</button>
% endif %}

Objetos como user com atributos como.is_authenticated vêm automaticamente do RequestContext do Django. Ou seja: quando você usa render(request, template_name, context), o Django já adiciona várias variáveis padrão no contexto do template — e user é uma delas.

user é o objeto do usuário autenticado, derivado de request.user. Se o usuário estiver logado, user é uma instância de django.contrib.auth.models.User. Se não estiver logado, user é um objeto AnonymousUser.

login_autenticacao.py
from django.contrib.auth.decorators import login_required

@login_required
def painel(request):
    return render(request, 'painel.html')

# Outra forma é, que se não estiver autenticado é redirecionado para a pagina de login
@login_required(login_url='users:login')
def painel(request):
    return render(request, 'painel.html')

redirect_field_name='next' pode ser usado como argumento em @login_required(login_url='users:login', redirect_field_name='next'), esse campo recebe a url da pagina que o usuário estava tentando acessar quando não estava logado, por exemplo.

logout_view.py
from django.contrib.auth import logout

def logout_view(request):
    if request.method == "POST":
        logout(request)
        return redirect('products:list')

| Exemplo model User

user_auth.py
Criar um usuário (Cadastro)
from django.contrib.auth.models import User
user = User.objects.create_user(
    username='joao',      # nome de usuário
    password='senha123',  # senha
    email='joao@email.com' # email (opcional)
)
print("Usuário criado com sucesso!")

# Verificar se o usuário existe e se a senha está correta (Login)
from django.contrib.auth import authenticate
user = authenticate(username='joao', password='senha123')
if user is not None:
    print("Login realizado com sucesso!")
else:
    print("Usuário ou senha incorretos.")

# Alterar informações do usuário
from django.contrib.auth.models import User
user = User.objects.get(username='joao')
user.email = 'novoemail@email.com'
user.save()
print("Email atualizado com sucesso!")

# Deletar um usuário
from django.contrib.auth.models import User
user = User.objects.get(username='joao')
user.delete()
print("Usuário deletado!")
user_models.py
from django.db import models
from django.contrib.auth.models import User

class Anotacao(models.Model):
    usuario = models.ForeignKey(User, on_delete=models.CASCADE) # Usando os usuários criados do django como chave estrangeira
    titulo = models.CharField(max_length=100)
    descricao = models.TextField()
    criado_em = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.titulo

exemplo de uso em um modelo

| Criptografia de Senhas em Formulários

view_password.py
from django.shortcuts import render, redirect
from .forms import CustomRegisterForm

def register_view(request):
    form = CustomRegisterForm(request.POST or None)

    if form.is_valid():
        user = form.save(commit=False) # não comita as alterações no banco de dados ainda
        user.set_password(user.password) # criptografa a senha do formulário antes de salvar
        user.save()
        return redirect('success')  # redireciona após o cadastro

    return render(request, 'register.html', {'form': form})

Criptografia de password vindo de um formulário preenchido (usando metodo set_password). Usada para não salvar textos comuns em campos de senha.

forms_passwords.py
from django import forms
from django.contrib.auth.models import User

class CustomRegisterForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ['username', 'email', 'password']

OAuth2 (Open Authorization 2.0)

OAuth2 (Open Authorization 2.0) é um padrão de autorização que permite que aplicações de terceiros acessem recursos de um usuário em outro serviço (como Google, Facebook, GitHub) sem precisar da senha dele.

Termo O que é
Client Quem quer o acesso (ex: seu site/app)
Resource Owner O usuário
Authorization Server Quem autentica (ex: Google)
Access Token Chave temporária pra acessar os dados do usuário
Refresh Token Usado pra renovar o access token sem pedir novo login

O django-allauth é um pacote com otima integração com django (documentação aqui). Django django-allauth um extra requirement — um “pacote opcional extra” chamado django-allauth[socialaccount]. com esse pacote extra, além da autenticação tradicional, você instala também as dependências necessárias para login social.

Acesse o provider desejado para criar credenciais (nesse caso github):

  • Entre em settings de seu perfil (https://github.com/settings/profile)

  • Clique em developer settings

  • Clique em OAuth apps -> new oauth app

  • De um nome para o app, e na url passe a url que o django está em execução (se local, http://localhost:8000)

  • Em Authorization callback URL insira: http://localhost:8000/accounts/github/login/callback/

  • Registre a aplicação e copie client_id para inserir em settings. Gere também um client_secret para fazer o mesmo procedimento.

Depois que tudo estiver pronto é possivel usar o link da midia social dentro de sua aplicação exemplo: http://localhost:9000/accounts/github/login/?process=login 

Instalar pacote

bash
$ pip install django-allauth
$ pip install "django-allauth[socialaccount]" # Pacote adicional para login social
$ pip install "django-allauth[socialaccount,google,github]" # caso precise de providers como o google, git etc...

| Exemplo Oauth2

O exemplo abaixo é com integração com github. Com as configurações abaixo o allauth vai cuidar de:

  • Criação de usuários automáticos

  • Login, logout e verificação de email (se quiser)

  • UI básica já pronta

  • Integração fácil com o admin

settings.py
INSTALLED_APPS = [
    ...
    'django.contrib.sites',  # Necessário
    'allauth', # Necessário
    'allauth.account', # Necessário
    'allauth.socialaccount', # Necessário
    'allauth.socialaccount.providers.github',  # Poderia ser com o google também
]

SITE_ID = 1

# Lista nova
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]

MIDDLEWARE = (
    "allauth.account.middleware.AccountMiddleware", # Add the account middleware
)

# Para cada provedor de conta social adicione um app
SOCIALACCOUNT_PROVIDERS = {
    'github': {
        'APP': {
            'client_id': '123',
            'secret': '456',
            'key': ''
        }
    }
}

LOGIN_REDIRECT_URL = '/members' # Rediciona para members após login feito com sucesso
SOCIALACCOUNT_LOGIN_ON_GET = True
ACCOUNT_LOGOUT_ON_GET = True
LOGOUT_REDIRECT_URL = '/'

O SITE_ID informa ao Django qual entrada da tabela django_site representa o "site atual".

Se você não define o SITE_ID, o Django não sabe qual domínio usar — e ao tentar acessar qualquer funcionalidade que dependa disso (como o login do admin ou do allauth), ele tenta buscar um site que não está definido, causando o erro: Site matching query does not exist.

Como SITE_ID o django diz:  “Use a entrada da tabela django_site com id=1 como meu site principal.”

Se não for definido LOGIN_REDIRECT_URL, o Django redireciona o usuário para /accounts/profile/ após o login.

Configuração Função
SOCIALACCOUNT_LOGIN_ON_GET Login automático no callback social. sem clique extra.
ACCOUNT_LOGOUT_ON_GET Logout via GET (acesso direto à URL de logout).
LOGOUT_REDIRECT_URL Redireciona para / após logout.

urls_principal.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('allauth.urls')),  # Login, logout, etc.
]

Após isso rode o comando migrate. Isso para todas as tabelas serem geradas.
Agora você tem as rotas:

  • /accounts/ # note a barra no fim

  • /accounts/login/

  • /accounts/logout/

  • /accounts/signup/

  • /accounts/github/login/ etc.

template.html
<a href="{% provider_login_url 'google' %}">Entrar com GitHub</a>

Flash Messages

Flash Messages são mensagens temporárias, que aparecem apenas uma vez para o usuário, geralmente depois de uma ação (exemplo: enviar um formulário, fazer login, excluir algo).Elas existem apenas por uma requisição, ou seja, ela só aparece depois do redirect e depois desaparece.

Ao executar messages.success(request, "Recipes loaded successfully"), Django salva essa mensagem dentro da session do usuário, na sessão ou no cookie. Na próxima requisição (por exemplo, depois de um redirect() ou render()), quando o template chama o bloco especial {% for message in messages %}, o Django recupera as mensagens da session ou dos cookies, e esvazia o armazenamento logo depois de exibir.

Etapa O que acontece?
Você adiciona uma mensagem Django salva na sessão/cookies durante a requisição atual (exemplo: dentro da sua view).
O navegador faz a próxima requisição Pode ser um redirect, ou um simples render. O Django recupera as mensagens salvas.
O template (se tiver) pode exibir a mensagem Se você usar {% for message in messages %} no template.
Após o Django ler as mensagens O Django limpa/consome as mensagens. Elas são removidas da sessão.
Na requisição seguinte depois disso As mensagens já sumiram (se não foram mostradas na anterior, perderam-se).

| Flash Messages

views_flash_message.py
from django.contrib import messages
from django.shortcuts import redirect

def minha_view(request):
    # Faz alguma ação (ex: salva um formulário)
    messages.success(request, 'Cadastro realizado com sucesso!')
    return redirect('home')  # Redireciona para alguma URL

def outra_view(request):
    messages.info(request, 'Este é um aviso informativo.')
    messages.warning(request, 'Cuidado com os dados inseridos.')
    messages.error(request, 'Erro ao salvar!')
    return redirect('outra_url')
flash_message.html
{% if messages %}
    <ul>
        {% for message in messages %}
            <li class="{{ message.tags }}">{{ message }}</li>
        {% endfor %}
    </ul>
{% endif %}

Isso vai aplicar classes CSS como success, error, info etc., automaticamente. mas sem aplicar nenhum estilo.

settings_custom_messages.py
from django.contrib.messages import constants


MESSAGE_TAGS = {
    constants.DEBUG: 'message-debug',
    constants.ERROR: 'message-error',
    constants.INFO: 'message-info',
    constants.SUCCESS: 'message-success',
    constants.WARNING: 'message-warning',
}

Se desejar, é possivel personalizar mensagens informando suas classes css no settings.py. Nesse caso message-debugmessage-error e etc, são classes personalizadas feitas no css. Se você não configurar o MESSAGE_TAGS, o Django usaria as classes padrões, tipo: success, error, info, etc.

Exemplo de uso: {% for message in messages %}<div class="message {{ message.tags }}">{{ message }}</div>{% endfor %}