FormView do Django

Resumo : neste tutorial, você aprenderá como usar a FormViewclasse Django para criar um formulário de registro para o aplicativo Todo.

Este tutorial começa onde o  tutorial Django LoginView  parou.

A classe Django FormViewpermite criar uma visualização que exibe um formulário. Usaremos a FormViewclasse para criar um formulário de registro para o Todo App .

Criando um formulário de inscrição

Crie form.spyum arquivo no usersaplicativo e defina a RegisterFormclasse da seguinte forma:

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User


class RegisterForm(UserCreationForm):
    email = forms.EmailField(max_length=254)

    class Meta:
        model = User
        fields = ('username',  'email', 'password1', 'password2', )Linguagem de código:  Python  ( python )

O RegisterFormusa o Usermodelo e exibe os campos nome de usuário, email, senha1 e senha2.

Definindo uma classe RegisterView

Defina a RegisterViewclasse views.pydo users.pyaplicativo:

from django.urls import reverse_lazy
from django.views.generic.edit import FormView
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login 
from django.contrib.auth.models import User
from .forms import RegisterForm


class RegisterView(FormView):
    template_name = 'users/register.html'
    form_class = RegisterForm
    redirect_authenticated_user = True
    success_url = reverse_lazy('tasks')
    
    def form_valid(self, form):
        user = form.save()
        if user:
            login(self.request, user)
        
        return super(RegisterView, self).form_valid(form)Linguagem de código:  Python  ( python )

A classe RegisterView herda da classe FormView e possui os seguintes atributos e métodos:

  • template_nameespecifica o nome do modelo para renderizar o formulário de inscrição.
  • form_classespecifica o formulário ( RegisterForm) usado no modelo.
  • redirect_authenticated_useré definido como True para redirecionar o usuário depois de autenticado.
  • success_urlespecifica o URL a ser redirecionado assim que o usuário se inscrever com sucesso. Neste exemplo, ele redireciona o usuário para a lista de tarefas.
  • form_valid()O método é chamado assim que o formulário é enviado com sucesso. Neste exemplo, salvamos o Usermodelo e logamos o usuário automaticamente.

Definindo a rota de registro

Defina uma rota que mapeie a URL de registro register/com o resultado do as_view()método da RegisterViewclasse no urls.pyapp users:

from django.urls import path
from django.contrib.auth.views import LogoutView
from .views import MyLoginView, RegisterView
 

urlpatterns = [
    path('login/', MyLoginView.as_view(),name='login'),
    path('logout/', LogoutView.as_view(next_page='login'),name='logout'),
    path('register/', RegisterView.as_view(),name='register'),
]
Linguagem de código:  Python  ( python )

Crie um modelo de registro

Crie um register.htmlno templates/usersdiretório do usersaplicativo com o seguinte código:

{%extends 'base.html'%}

{%block content%}
	<div class="center">
	  <form method="post" novaldiate class="card">
	  	{% csrf_token %}
	    <h2 class="text-center">Create your account</h2>
		{% for field in form %}
	    		{{ field.label_tag }} 
	        	{{ field }}
	        	{% if field.errors %}
	        		<small class="error">{{ field.errors|striptags  }}</small> 
	        	{% endif %}
		{% endfor %}
		
		<input type="submit" value="Register" class="btn btn-primary full-width">
		<hr>
		<p class="text-center">Already have an account? <a href="{% url 'login'%}">Login Here</a></p>
		</form>
	</div>
{%endblock content%}Linguagem de código:  HTML, XML  ( xml )

O formulário em users/register.htmlé a RegisterFormclasse que definimos no forms.pyarquivo.

Adicionando link de registro ao login e navegação

Modifique o login.htmlmodelo adicionando o link de registro:

{%extends 'base.html'%}

{%block content%}
  <div class="center">
	  <form method="post" class="card" novalidate>
	  	{% csrf_token %}
	    <h2 class="text-center">Log in to your account</h2>
		{% for field in form %}
	    		{{ field.label_tag }} 
	        	{{ field }}
	        	{% if field.errors %}
	        		<small>{{ field.errors|striptags  }}</small> 
	        	{% endif %}
		{% endfor %}
		
		<input type="submit" value="Login" class="btn btn-primary full-width">
		<hr>
		<p class="text-center">Forgot your password <a href="#">Reset Password</a></p>
		<p class="text-center">Don't have a account? <a href="{%url 'register'%}">Join Now</a></p>
	</form>
</div>

{%endblock content%}
Linguagem de código:  HTML, XML  ( xml )

Além disso, modifique o base.htmlmodelo adicionando o link de registro à navegação e à página inicial:

{%load static %}
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="{% static 'css/style.css' %}" />
        <title>Todo List</title>
    </head>

    <body>
        <header class="header">
            <div class="container">
            	<a href="{%url 'home'%}" class="logo">Todo</a>
            	<nav class="nav">
	            	<a href="{%url 'home'%}"><i class="bi bi-house-fill"></i> Home</a>
	                {% if request.user.is_authenticated %}
	    	              	<a href="{% url 'tasks' %}"><i class="bi bi-list-task"></i> My Tasks</a>
	    	              	<a href="{% url 'task-create' %}"><i class="bi bi-plus-circle"></i> Create Task</a>
		                <a href="#">Hi {{request.user | title}}</a>
	    	                <a href="{% url 'logout' %}" class="btn btn-outline">Logout</a>
	                {% else %}
				<a href="{% url 'login' %}" class="btn btn-outline">Login</a>
	            	        <a href="{% url 'register' %}" class="btn btn-primary">Join Now</a>
	                {% endif %}
	             </nav>
            </div>
        </header>
        <main>
            <div class="container">
            	{% if messages %}
			{% for message in messages %}
			<div class="alert alert-{{message.tags}}">
			       {{message}}
		        </div>
		        {% endfor %}
		{% endif %}
            
             {%block content %}
             {%endblock content%}
            </div>
        </main>
        <footer class="footer">
            <div class="container">
                <p>© Copyright {% now "Y" %} by <a href="https://tutorials.acervolima.com">Python Tutorial</a></p>
            </div>
        </footer>
    </body>

</html>
Linguagem de código:  HTML, XML  ( xml )

home.html

{%extends 'base.html'%}

{%load static %}

{%block content%}
	<section class="feature">
		<div class="feature-content">
			<h1>Todo</h1>
			<p>Todo helps you more focus, either work or play.</p>	
			<a class="btn btn-primary cta" href="{% url 'register' %}">Get Started</a>
		</div>
		<img src="{%static 'images/feature.jpg'%}" alt="" class="feature-image">
	</section>
{%endblock content%}
Linguagem de código:  HTML, XML  ( xml )

Se você abrir o URL de registro:

http://127.0.0.1:8000/register/Linguagem de código:  Python  ( python )

você verá o formulário de registro:

Depois de registrado com sucesso, você fará login automaticamente:

No entanto, temos um problema. Jane pode visualizar, atualizar e excluir tarefas de outros usuários.

Para corrigir isso, você precisa filtrar as tarefas que pertencem ao usuário atualmente logado em todas as classes adicionando os get_queryset()métodos às classes TaskList, TaskDetail, TaskCreate, TaskUpdate, TaskDelete.

from django.shortcuts import render
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages
from .models import Task


class TaskList(LoginRequiredMixin, ListView):
    model = Task
    context_object_name = 'tasks'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['tasks'] = context['tasks'].filter(user=self.request.user)
        return context
    
class TaskDetail(LoginRequiredMixin, DetailView):
    model = Task
    context_object_name = 'task'
    
    def get_queryset(self):
        base_qs = super(TaskDetail, self).get_queryset()
        return base_qs.filter(user=self.request.user)  
    
    
class TaskUpdate(LoginRequiredMixin, UpdateView):
    model = Task
    fields = ['title','description','completed']
    success_url = reverse_lazy('tasks')
    
    def form_valid(self, form):
        messages.success(self.request, "The task was updated successfully.")
        return super(TaskUpdate,self).form_valid(form)
      
    def get_queryset(self):
        base_qs = super(TaskUpdate, self).get_queryset()
        return base_qs.filter(user=self.request.user)
 

class TaskDelete(LoginRequiredMixin, DeleteView):
    model = Task
    context_object_name = 'task'
    success_url = reverse_lazy('tasks')
    
    def form_valid(self, form):
        messages.success(self.request, "The task was deleted successfully.")
        return super(TaskDelete,self).form_valid(form)
      
    def get_queryset(self):
        base_qs = super(TaskDelete, self).get_queryset()
        return base_qs.filter(user=self.request.user)
Linguagem de código:  Python  ( python )

Agora, se você fizer login como Jane, verá uma lista de tarefas vazia:

Django formview - lista de tarefas vazia

Se você criar uma nova tarefa, verá apenas essa tarefa na lista de tarefas:

Se você tentar acessar as tarefas de John enquanto estiver fazendo login como Jane, receberá um erro 404 como este:

visualização de formulário do Django - 404

Você pode baixar o código completo aqui.

Resumo

  • Use Django FormViewpara criar uma view que exibe um formulário.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *