Мы почти подошли к концу этого руководства. В этой части мы займемся логином и регистрацией пользователей. Django предоставляет нам довольно простую и настраиваемую систему аутентификации и авторизации.
Для начала мы должны указать по каким адресам будет осуществляться вход, перенаправление для входа и перенаправление для выхода. Для этого откроем наш файл simple_blog/settings.py и в конце его добавим следующие строки:
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
Code language: JavaScript (javascript)
Далее мы создадим файл users/url.py и перенесем туда урлы входа и регистрации, которые находились в файле simple_blog/urls.py. Теперь эти два файла будут выглядеть следующим образом:
simple_blog/urls.py
from django.contrib import admin
from django.urls import path, include
from django.views.generic import TemplateView
urlpatterns = [
path('admin/', admin.site.urls),
path(
route='',
view=TemplateView.as_view(template_name='posts/index.html'),
name='index'
),
path(
route='post/my-post.html',
view=TemplateView.as_view(template_name='posts/detail.html'),
name='detail'
),
path(
route='about',
view=TemplateView.as_view(template_name='about.html'),
name='about'
),
path('', include(('users.urls', 'users'), namespace='users')),
Code language: JavaScript (javascript)
users/url.py
"""Users URLs."""
# Django
from django.urls import path
from django.views.generic import TemplateView
# View
from users import views
urlpatterns = [
path(
route='login',
view=views.LoginView.as_view(),
name='login'
),
path(
route='register',
view=views.SignupView.as_view(),
name='register'
),
path(
route='logout/',
view=views.LogoutView.as_view(),
name='logout'
),
path(
route='register_completed/',
view=TemplateView.as_view(template_name='users/registerok.html'),
name='registerok'
),
]
Code language: PHP (php)
Url для входа и регистрации были обновлены и теперь указывают на файл users/views.py и классы, которые обеспечивают их функциональность. Мы также создали путь для полной регистрации, который указывает на шаблон, который мы сейчас создадим, и для выхода из системы.
Далее мы займемся созданием формы регистрации, для чего создадим файл users/forms.py и введем следующие строки кода:
"""User forms.""" # Django from django import forms # Models from django.contrib.auth.models import User from users.models import Profile class SignupForm(forms.Form): """Sign up form.""" email = forms.CharField( min_length=6, max_length=70, widget=forms.EmailInput() ) username = forms.CharField( min_length=6, max_length=70, widget=forms.TextInput() ) password = forms.CharField( max_length=70, widget=forms.PasswordInput() ) password_confirmation = forms.CharField( max_length=70, widget=forms.PasswordInput() ) def clean(self): """Verify password confirmation match.""" data = super().clean() password = data['password'] password_confirmation = data['password_confirmation'] if password != password_confirmation: raise forms.ValidationError('Пароли не совпадают.') return data def save(self): """Create user and profile.""" data = self.cleaned_data data.pop('password_confirmation') user = User.objects.create_user(**data) profile = Profile(user=user) profile.save()
Здесь мы объявляем класс SignupForm, который будет содержать все поля нашей формы. В данном случае мы объявляем все поля типа text. Для email это будет input mail, имя пользователя типа input text, а для паролей типа password.
Затем мы определим функцию clean, которая будет выполняться после отправки формы и будет проверять, совпадает ли пароль с повторным его вводом.
Наконец, мы создадим функцию save, которая удалит поле password_confirmation и сохранит переданную информацию в таблице User and Profile.
Давайте теперь займемся частью представления, для этого откроем файл users/views.py и добавим следующий код:
from django.shortcuts import render from django.views.generic import FormView from django.urls import reverse, reverse_lazy from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth import views as auth_views # Forms from users.forms import SignupForm class SignupView(FormView): """Users sign up view.""" template_name = 'users/register.html' form_class = SignupForm success_url = reverse_lazy('users:registerok') def form_valid(self, form): """Save form data.""" form.save() return super().form_valid(form)
Для регистрации мы используем одно из общих представлений, которые есть в django, в данном случае FormView.
В template_name мы передаем шаблон, который будем использовать.
В form_class формы, которую мы создали ранее.
success_url будет url для перенаправления, если все прошло успешно.
Наконец, мы используем функцию form_valid для сохранения пользователя, если все прошло успешно.
Изменим шаблон, который мы создали для регистрации в руководстве по дизайну (в предыдущем посте). Для этого откроем файл templates/users/register.html и заменим код на следующий:
{% extends "users/base.html" %}
{% block title %}Simple blog - Register{% endblock %}
{% block content %}
<form class="form-signin" method="POST">
{% csrf_token %}
<h1><a href="#" class="title-link">Simple Blog</a></h1>
<h1 class="h3 mb-3 font-weight-normal">Register</h1>
<label for="id_email" class="sr-only">Email</label>
<input type="email" name="email" id="id_email" class="form-control" placeholder="Email" required autofocus>
<label for="id_username" class="sr-only">Имя пользователя</label>
<input type="text" name="username" id="id_username" class="form-control" placeholder="Имя пользователя" required>
<label for="inputPassword" class="sr-only">Пароль</label>
<input type="password" name="password" id="id_password" class="form-control" placeholder="Пароль" required>
<label for="inputPassword" class="sr-only">Повторите пароль</label>
<input type="password" name="password_confirmation" id="id_password_confirmation" class="form-control" placeholder="Повторите пароль" required>
<div class="checkbox mb-3"></div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Зарегистрироваться</button>
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<p class="mt-5 mb-3 text-muted">© Simple Blog {% now "Y" %}</p>
</form>
{% endblock %}
Code language: HTML, XML (xml)
Изменения, которые мы сделали, заключаются в модификации формы, чтобы django перехватывал поля, которые мы собираемся отправить. Добавляем csrf_token, который нам понадобится для валидации формы. Если при создании пользователя возникнут ошибки, будет показано предупреждение.
Если при создании пользователя все прошло успешно, мы отправим в шаблон уведомление о том, что пользователь создан. Для этого необходимо создать файл templates/users/registerok.html и добавить в него этот код:
{% extends "users/base.html" %}
{% block title %}Simple blog - Регистрация завершена{% endblock %}
{% block content %}
<main role="main" class="container">
<div class="starter-template">
<h1>Пользователь успешно создан</h1>
<p class="lead">Если страница не будет перенаправлена в течение 5 секунд, нажмите ссылку<a href="{% url 'users:login' %}">здесь</a></p>
</div>
</main>
<script>
setTimeout(function(){
window.location.replace("{% url 'users:login' %}");
}, 5000);
</script>
{% endblock %}
Code language: HTML, XML (xml)
Здесь мы выводим сообщение и перенаправляем на страницу входа с помощью {% url ‘users:login’ %}, который находится в наших файлах urls.py и генерирует url на основе пространства имен и имени, которые мы добавили в urls.
Для доступа к регистрации мы заходим на эту страницу https://127.0.0.1:8000/register и можем создать пользователя для последующего тестирования.
Теперь, когда у нас есть регистрационная часть, мы приступаем к работе с частью входа в систему. Мы открываем наш файл users/views.py и в конце его добавляем следующие строки:
class LoginView(auth_views.LoginView): """Login view.""" template_name = 'users/login.html' class LogoutView(LoginRequiredMixin, auth_views.LogoutView): """Logout view.""" template_name = 'users/logged_out.html'
Шаблон назначается классу LoginView, а вся логика выполняется Django. В случае с выходом из системы все точно так же, хотя. В этом случае шаблон не нужен, но мы добавляем его (даже если он не существует). На этом часть представления готова.
В завершение откроем файл templates/users/login.html и изменим существующий код на следующий:
{% extends "users/base.html" %}
{% block content %}
<form method="POST" action="{% url "users:login" %}" class="form-signin">
{% csrf_token %}
<h1><a href="#" class="title-link">Simple Blog</a></h1>
<h1 class="h3 mb-3 font-weight-normal">Login</h1>
<label for="id_username" class="sr-only">Пользователь</label>
<input type="text" id="id_username" class="form-control" placeholder="Пользователь" name="username" required autofocus>
<label for="id_password" class="sr-only">Пароль</label>
<input type="password" id="id_password" class="form-control" placeholder="Пароль" name="password" required>
<div class="checkbox mb-3"></div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Login</button>
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<p class="mt-5 mb-3 text-muted">© Simple Blog {% now "Y" %}</p>
</form>
{% endblock %}
Code language: HTML, XML (xml)
Как и в шаблоне регистрации, мы добавляем csrf_token и, если есть ошибки, фиксируем их.
Заключение
Как вы видите, создать систему входа в Django очень просто. В следующем посте мы рассмотрим, как связать весь проект, работающий с представлениями.