Создание страницы регистрации пользователей Django в Python
В этом уроке вы узнаете, как создать в Python форму регистрации и страницы входа в Django, которая позволит пользователям зарегистрироваться.
- Создание формы регистрации Django
- Настройка формы регистрации Django
- Обработка логики регистрации
- Добавление ссылок
- Запрет пользователю редактировать/удалять сообщения других пользователей
- Удаление автора из формы создания поста
Создание формы регистрации Django
Сначала определите URL-адрес регистрации в urls.py приложения пользователя:
from django.urls import path from . import views urlpatterns = [ path('login/', views.sign_in, name='login'), path('logout/', views.sign_out, name='logout'), path('register/', views.sign_up, name='register'), ]
Во-вторых, определите класс RegisterForm в forms.py файла users.py:
from django import forms from django.contrib.auth.models import User from django.contrib.auth.forms import UserCreationForm class LoginForm(forms.Form): username = forms.CharField(max_length=65) password = forms.CharField(max_length=65, widget=forms.PasswordInput) class RegisterForm(UserCreationForm): class Meta: model=User fields = ['username','email','password1','password2']
RegisterForm использует встроенную модель User и включает четыре поля, включая имя пользователя, адрес электронной почты, пароль1 и пароль2, которые пользователь должен заполнить для регистрации.
В-третьих, определите функцию представления sign_up() в файле views.py приложения пользователя:
from django.shortcuts import render, redirect from django.contrib import messages from django.contrib.auth import login, authenticate, logout from .forms import LoginForm, RegisterForm def sign_up(request): if request.method == 'GET': form = RegisterForm() return render(request, 'users/register.html', { 'form': form})
Функция представления sign_up() создает объект RegisterForm и отображает его в шаблоне register.html.
В-четвертых, создайте шаблон register.html в каталоге templates/users приложения users:
{% extends 'base.html' %} {% block content %} <form method="POST" novalidate> {% csrf_token %} <h2>Sign Up</h2> {{ form.as_p }} <input type="submit" value="Register" /> </form> {% endblock content%}
Registerl.html расширяет шаблон base.html проекта. Он отображает RegisterForm(форму).
Обратите внимание, что свойство novalidate удаляет проверку HTML5. После завершения проекта вы можете удалить это свойство, чтобы включить проверку HTML5.
Наконец, откройте URL-адрес регистрации:
http://127.0.0.1:8000/register/
…вы увидите следующую форму регистрации:
Настройка формы регистрации Django
Регистрационная форма имеет четыре поля с большим количеством информации. Эта информация берется из модели User по умолчанию.
Если вы хотите настроить информацию, отображаемую в форме, вы можете изменить шаблон register.html следующим образом:
{% extends 'base.html' %} {% block content %} <form method="POST" novalidate> {% csrf_token %} <h2>Sign Up</h2> {% for field in form %} <p> {% if field.errors %} <ul class="errorlist"> {% for error in field.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} {{ field.label_tag }} {{ field }} </p> {% endfor %} <input type="submit" value="Register" /> </form> {% endblock content%}
Шаблон перебирает поля формы и выводит каждое поле по отдельности. Для каждого поля он отображает список ошибок, если проверка не пройдена.
Новая форма будет выглядеть так:
Если вы заполните информацию и нажмете «Зарегистрироваться», вы получите сообщение об ошибке, поскольку мы не добавили код, обрабатывающий HTTP-запрос POST.
Обработка логики регистрации
Для обработки HTTP-запроса POST необходимо изменить функцию sign_up() в файле views.py приложения пользователя:
def sign_up(request): if request.method == 'GET': form = RegisterForm() return render(request, 'users/register.html', {'form': form}) if request.method == 'POST': form = RegisterForm(request.POST) if form.is_valid(): user = form.save(commit=False) user.username = user.username.lower() user.save() messages.success(request, 'You have singed up successfully.') login(request, user) return redirect('posts') else: return render(request, 'users/register.html', {'form': form})
Как это работает.
Сначала создайте новый экземпляр RegisterForm:
form = RegisterForm(request.POST)
Если форма действительна, мы сохраняем форму, но не сохраняем ее немедленно в базе данных. Это делается путем передачи аргумента commit=False в метод save() объекта формы.
Причина в том, что мы хотим сделать имя пользователя строчным перед сохранением его в базе данных:
user.username = user.username.lower() user.save()
После сохранения пользователя мы создаем флэш-сообщение, авторизуем пользователя и перенаправляем его на страницу списка сообщений:
messages.success(request, 'You have singed up successfully.') login(request, user) return redirect('posts')
Если форма недействительна, мы перерисовываем форму с ранее введенными значениями, передавая объект формы в функцию render():
return render(request, 'users/register.html', {'form': form})
Следующий пример иллюстрирует, как зарегистрировать пользователя с именем jane:
Добавление ссылок
- Сначала включите ссылку на регистрацию, изменив шаблон 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' %}" /> <script src="{% static 'js/app.js' %}" defer></script> <title>My Site</title> </head> <body> <header> {%if request.user.is_authenticated %} <a href="{% url 'posts' %}">My Posts</a> <a href="{% url 'post-create' %}">New Post</a> <span>Hi {{ request.user.username | title }}</span> <a href="{% url 'logout' %}">Logout</a> {%else%} <a href="{% url 'login' %}">Login</a> <a href="{% url 'register' %}">Register</a> {%endif%} </header> <main> {% if messages %} <div class="messages"> {% for message in messages %} <div class="alert {% if message.tags %}alert-{{ message.tags }}"{% endif %}> {{ message }} </div> {% endfor %} </div> {% endif %} {%block content%} {%endblock content%} </main> </body> </html>
- Во-вторых, включите ссылку на регистрацию в шаблон login.html:
{% extends 'base.html' %} {% block content %} <form method="POST" novalidate> {% csrf_token %} <h2>Login</h2> {{form.as_p}} <input type="submit" value="Login" /> <p>Don't have an account? <a href="{%url 'register' %}">Register</a></p> </form> {% endblock content%}
- В-третьих, добавьте ссылку для входа на страницу register.html:
{% extends 'base.html' %} {% block content %} <form method="POST" novalidate> {% csrf_token %} <h2>Sign Up</h2> {% for field in form %} <p> {% if field.errors %} <ul class="errorlist"> {% for error in field.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} {{ field.label_tag }} {{ field }} </p> {% endfor %} <input type="submit" value="Register" /> <p>Already has an account? <a href="{%url 'login' %}">Login</a></p> </form> {% endblock content%}
Запрет пользователю редактировать/удалять сообщения других пользователей
Обычно пользователь не должен иметь возможности редактировать или удалять посты других пользователей. Однако пользователь может просматривать посты других пользователей.
Для реализации этой функции нам нужно проверить, является ли автор поста тем же, что и авторизованный в данный момент пользователь. Если да, мы отображаем формы редактирования/удаления. В противном случае мы можем перенаправить пользователей на страницу 404.
Также нам необходимо скрыть ссылки редактирования и удаления на странице списка сообщений, если сообщения не принадлежат пользователю.
Сначала измените views.py приложения блога:
from django.shortcuts import render,redirect, get_object_or_404 from django.contrib import messages from django.contrib.auth.decorators import login_required from .models import Post from .forms import PostForm @login_required def delete_post(request, id): queryset = Post.objects.filter(author=request.user) post = get_object_or_404(queryset, pk=id) context = {'post': post} if request.method == 'GET': return render(request, 'blog/post_confirm_delete.html',context) elif request.method == 'POST': post.delete() messages.success(request, 'The post has been deleted successfully.') return redirect('posts') @login_required def edit_post(request, id): queryset = Post.objects.filter(author=request.user) post = get_object_or_404(queryset, pk=id) if request.method == 'GET': context = {'form': PostForm(instance=post), 'id': id} return render(request,'blog/post_form.html',context) elif request.method == 'POST': form = PostForm(request.POST, instance=post) if form.is_valid(): form.save() messages.success(request, 'The post has been updated successfully.') return redirect('posts') else: messages.error(request, 'Please correct the following errors:') return render(request,'blog/post_form.html',{'form':form}) @login_required def create_post(request): if request.method == 'GET': context = {'form': PostForm()} return render(request,'blog/post_form.html',context) elif request.method == 'POST': form = PostForm(request.POST) if form.is_valid(): form.save() messages.success(request, 'The post has been created successfully.') return redirect('posts') else: messages.error(request, 'Please correct the following errors:') return render(request,'blog/post_form.html',{'form':form}) def home(request): posts = Post.objects.all() context = {'posts': posts } return render(request,'blog/home.html', context)
И при удалении, и при обновлении мы фильтруем публикацию по текущему пользователю, прежде чем передать ее в функцию get_object_or_404().
Если вы войдете в систему как Джейн и попытаетесь отредактировать пост, который не принадлежит Джейн, вы получите ошибку 404. Например:
Страница 404:
Во-вторых, измените шаблон home.html, чтобы скрыть ссылки редактирования и удаления.
{% extends 'base.html' %} {% block content %} <h1>My Posts</h1> {% for post in posts %} <h2>{{ post.title }}</h2> <small>Published on {{ post.published_at | date:"M d, Y" }} by {{ post.author | title}}</small> <p>{{ post.content }}</p> {% if request.user.is_authenticated and request.user == post.author %} <p> <a href="{% url 'post-edit' post.id %}">Edit</a> <a href="{% url 'post-delete' post.id%}">Delete</a> </p> {% endif %} {% endfor %} {% endblock content %}
Удаление автора из формы создания поста
Сначала удалите поле автора из полей класса PostForm:
from django.forms import ModelForm from .models import Post class PostForm(ModelForm): class Meta: model = Post fields = ['title','content']
Форма после создания будет выглядеть так:
Во-вторых, измените функцию create_post() в файле views.py приложения блога, чтобы обновить автора поста до текущего вошедшего в систему пользователя:
@login_required def create_post(request): if request.method == 'GET': context = {'form': PostForm()} return render(request,'blog/post_form.html',context) elif request.method == 'POST': form = PostForm(request.POST) if form.is_valid(): user = form.save(commit=False) user.author = request.user user.save() messages.success(request, 'The post has been created successfully.') return redirect('posts') else: messages.error(request, 'Please correct the following errors:') return render(request,'blog/post_form.html',{'form':form})