Django FormView в Python — как использовать

Класс Django FormView позволяет создать представление, отображающее форму. Мы будем использовать класс FormView для создания формы регистрации для приложения Todo в Python.

Содержание

Создание формы регистрации

Создайте файл form.spy в приложении пользователя и определите класс RegisterForm следующим образом:

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', )

RegisterForm использует модель User и отображает поля имени пользователя, электронной почты, пароля1 и пароля2.

Определение класса RegisterView

Определите класс RegisterView в views.py приложения users.py:

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)

Класс RegisterView наследуется от класса FormView и имеет следующие атрибуты и методы:

  • template_name указывает имя шаблона для отображения формы регистрации.
  • form_class указывает форму (RegisterForm), используемую в шаблоне.
  • redirect_authenticated_user имеет значение True для перенаправления пользователя после аутентификации.
  • success_url указывает URL для перенаправления после успешной регистрации пользователя. В этом примере он перенаправляет пользователя в список задач.
  • Метод form_valid() вызывается после успешной отправки формы. В этом примере мы сохраняем модель User и автоматически входим в систему.

Определение маршрута регистрации

Определите маршрут, который сопоставляет URL-адрес регистрации register/ с результатом метода as_view() класса RegisterView в urls.py приложения пользователя:

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'),
]

Создание шаблона регистрации

Создайте файл register.html в каталоге templates/users приложения users со следующим кодом:

{%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%}

Форма в users/register.html — это класс RegisterForm, который мы определили в файле forms.py.

Добавление ссылки на регистрацию в систему входа и навигации

Измените шаблон login.html, добавив ссылку на регистрацию:

{%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%}

Также измените шаблон base.html, добавив ссылку на регистрацию в навигационную и домашнюю страницу:

{%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://www.pythontutorial.net">Python Tutorial</a></p>
            </div>
        </footer>
    </body>

</html>

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%}

Если вы откроете URL-адрес регистрации:

http://127.0.0.1:8000/register/

вы увидите форму регистрации:

Пример формы регистрации

После успешной регистрации вы автоматически войдете в систему:

Вход в систему после успешной регистрации

Однако у нас есть одна проблема. Jane может просматривать, обновлять и удалять задачи других пользователей.

Чтобы исправить это, необходимо отфильтровать задачи, принадлежащие текущему вошедшему в систему пользователю во всех классах, добавив методы get_queryset() в классы 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)

Теперь, если вы войдете в систему как Jane, вы увидите пустой список дел:

django formview - пустой список дел

Если вы создадите новую задачу, в списке дел вы увидите только ее:

Создание новой задачи в списке делОтображение новой задачи в списке дел

Если вы попытаетесь получить доступ к задачам Джона, войдя в систему как Джейн, вы получите ошибку 404, подобную этой:

django formview - ошибка 404

Похожие посты
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *