Авторизация и регистрация в Django
Django уже предоставляет встроенную систему django.contrib.auth. Мы будем пользоваться ей от части в нашем приложении "system".
Если вы используете такую же структуру папок, как я, то в папке modules/system/views я создам файл для представлений системы аутентификации: authenticated.py. Тоже самое я сделаю в папке modules/system/forms.
А теперь давайте создадим форму регистрации пользователя:
modules/system/forms/authenticated.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class UserRegisterForm(UserCreationForm):
"""
Переопределенная форма регистрации пользователей
"""
class Meta(UserCreationForm.Meta):
fields = UserCreationForm.Meta.fields + ('email', 'first_name', 'last_name')
def clean_email(self):
"""
Проверка email на уникальность
"""
email = self.cleaned_data.get('email')
username = self.cleaned_data.get('username')
if email and User.objects.filter(email=email).exclude(username=username).exists():
raise forms.ValidationError('Email адрес должен быть уникальным')
return email
def __init__(self, *args, **kwargs):
"""
Обновление стилей формы регистрации
"""
super().__init__(*args, **kwargs)
for field in self.fields:
self.fields['username'].widget.attrs.update({"placeholder": 'Придумайте логин'})
self.fields['email'].widget.attrs.update({"placeholder": 'Введите ваш email'})
self.fields['first_name'].widget.attrs.update({"placeholder": 'Ваше имя'})
self.fields["last_name"].widget.attrs.update({"placeholder": 'Ваша фамилия'})
self.fields['password1'].widget.attrs.update({"placeholder": 'Придумайте свой пароль'})
self.fields['password2'].widget.attrs.update({"placeholder": 'Повторите придуманный пароль'})
self.fields[field].widget.attrs.update({"class": "form-control", "autocomplete": "off"})
Пояснения:
- Я наследуюсь от встроенной формы Django: UserCreationForm, добавляю ей необходимые новые поля, такие как email, first_name, last_name. Задаю bootstrap стили и placeholder's.
- Также я добавляю метод def clean_email для проверки на уникальность введенного email. Если email зарегистрирован уже в системе, второй раз его не получится использовать.
Далее я создам представление для нашей формы регистрации:
modules/system/views/authenticated.py
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.views.generic import CreateView
from modules.blog.forms.authenticated import UserRegisterForm
class RegisterCreateView(SuccessMessageMixin, CreateView):
"""
Представление регистрации на сайте с формой регистрации
"""
form_class = UserRegisterForm
success_url = reverse_lazy('home')
template_name = 'modules/system/authenticated/register.html'
success_message = 'Вы успешно зарегистрировались. Можете войти на сайт!'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'Регистрация на сайте'
return context
Пояснения:
- Я использую представление CreateView.
- Нашу форму UserRegisterForm
- При успешной регистрации отправляю пользователя на главную страницу
- Использую миксин SuccessMessageMixin для вывода сообщения об успешном завершении регистрации
Напоминаю, если используете ту же структуру папок, то не забываем про __init__.py во views и forms
modules/system/forms/__init__.py
from modules.system.forms.authenticated import *
from modules.system.forms.profiles import *
__all__ = '__all__'
modules/system/views/__init__.py
from modules.system.views.profiles import *
from modules.system.views.authenticated import *
__all__ = '__all__'
Добавляем в urls.py наше новое представление:
from django.urls import path
from modules.system.views import ProfileView, ProfileEditView, RegisterCreateView
urlpatterns = [
path('user/edit/', ProfileEditView.as_view(), name='profile-edit'),
path('user/<str:slug>/', ProfileView.as_view(), name='profile'),
path('register/', RegisterCreateView.as_view(), name='register'),
]
И создаем нужный шаблон с следующей формой:
templates/modules/system/authenticated/register.html
{% extends 'main.html' %}
{% block content %}
<div class="card mb-3 border-0 nth-shadow">
<div class="card-body">
<div class="card-title nth-card-title">
<h4>Регистрация на сайте</h4>
</div>
<form method="post" action="{% url 'register' %}" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-dark mt-2">Зарегистрироваться</button>
</form>
</div>
</div>
{% endblock %}
Пояснения:
- Оформил все в Bootstrap
- Обязательно action="{% url 'register' %}" на наше представление
Давайте проверим, как работает регистрация:

Попробую получить ограничение на email:

И регистрируемся:

После успешной регистрации нас перебрасывает на главную с сообщение об успешной регистрации.
Теперь давайте создадим форму для авторизации на сайте:
modules/system/forms/authenticated.py
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
class UserLoginForm(AuthenticationForm):
"""
Форма авторизации на сайте
"""
def __init__(self, *args, **kwargs):
"""
Обновление стилей формы регистрации
"""
super().__init__(*args, **kwargs)
for field in self.fields:
self.fields['username'].widget.attrs['placeholder'] = 'Введите ваш логин'
self.fields['password'].widget.attrs['placeholder'] = 'Введите ваш пароль'
self.fields['username'].label = 'Логин'
self.fields[field].widget.attrs.update({
'class': 'form-control',
'autocomplete': 'off'
})
Пояснения:
- В этой форме я наследуюсь от стандартной django формы AuthenticationForm.
- Задаю стили и на этом все.
Создадим необходимое представление для авторизации:
modules/system/views/authenticated.py
from django.contrib.auth.views import LoginView
class UserLoginView(SuccessMessageMixin, LoginView):
"""
Авторизация на сайте
"""
form_class = UserLoginForm
template_name = 'modules/system/authenticated/login.html'
next_page = 'home'
success_message = 'Добро пожаловать на сайт!'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'Авторизация на сайте'
return context
Пояснения:
- Наследуемся от встроенного представления LoginView, изменяя параметры next_page, form_class, template_name на свои.
- Добавляем миксин для уведомления.
Добавим ссылку на авторизацию:
modules/system/urls.py
from django.urls import path
from modules.system.views import ProfileView, ProfileEditView, RegisterCreateView, UserLoginView
urlpatterns = [
path('user/edit/', ProfileEditView.as_view(), name='profile-edit'),
path('user/<str:slug>/', ProfileView.as_view(), name='profile'),
path('register/', RegisterCreateView.as_view(), name='register'),
path('login/', UserLoginView.as_view(), name='login')
]
Создадим шаблон:
templates/modules/system/authenticated/login.html
{% extends 'main.html' %}
{% block content %}
<div class="card mb-3 border-0 nth-shadow">
<div class="card-body">
<div class="card-title nth-card-title">
<h4>Авторизация на сайте</h4>
</div>
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
{{ form.as_p }}
<div class="d-grid gap-2 d-md-block mt-2">
<button type="submit" class="btn btn-dark">Авторизоваться</button>
</div>
</form>
</div>
</div>
{% endblock %}
Отлично, давайте я попробую войти в аккаунт:

При нажатии на кнопку авторизоваться:

Отлично, я вошел в свой зарегистрированный аккаунт.

В следующем уроке мы создадим форму восстановления пароля и изменения пароля в профиле.