Django FormView в Python — как использовать
Класс Django FormView позволяет создать представление, отображающее форму. Мы будем использовать класс FormView для создания формы регистрации для приложения Todo в Python.
- Создание формы регистрации
- Определение класса RegisterView
- Определение маршрута регистрации
- Создание шаблона регистрации
- Добавление ссылки на регистрацию в систему входа и навигации
Создание формы регистрации
Создайте файл 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, вы увидите пустой список дел:
Если вы создадите новую задачу, в списке дел вы увидите только ее:
Если вы попытаетесь получить доступ к задачам Джона, войдя в систему как Джейн, вы получите ошибку 404, подобную этой: