🐍🚀 Django с нуля. Часть 2: регистрация, авторизация, ограничение доступа
Во второй части туториала будем разрабатывать систему регистрации и авторизации, а также ограничим доступ к просмотру профилей для неавторизованных посетителей блога.
Второй этап разработки
Продолжим работу над проектом с создания первой учетной записи для админа, а затем перейдем к разработке необходимых моделей для базы данных и форм регистрации / авторизации. Весь код второго этапа находится здесь.
Создание учетных записей и администрирование
Панель администрирования открывается по адресу http://localhost:8000/admin. Пока что войти в админку нельзя: сначала нужно создать учетную запись суперпользователя (админа). Перед началом этого процесса следует применить миграции: python manage.py migrate
(эту операцию мы намеренно пропустили на первом шаге).
После применения миграций можно приступать к созданию записи для суперпользователя: python manage.py createsuperuser
В ходе выполнения команды появится приглашение ввести имя пользователя, пароль и емейл (они не отображаются во время ввода – будьте внимательны). Учетная запись суперпользователя готова, запустите сервер и авторизуйтесь:
Кликните по ADD USER и создайте учетные записи для двух тестовых пользователей. Обратите внимание, что Джанго берет хэширование паролей на себя:
python manage.py changepassword <имя пользователя>
.Работа с базой данных и моделями
Одна из сильнейших сторон Джанго – простота подключения базы данных и возможность работать с любыми базами с помощью одного и того же кода (и без глубоких познаний в области языка запросов SQL). Django уже создал для нас файл models.py. Каждая модель представляет отдельную таблицу в базе. Откроем models.py и напишем код для модели Post.
Для обновления структуры базы создадим и выполним миграции: сначала запустим python manage.py makemigrations
, а затем python manage.py migrate
.
Теперь пора обновить файл blog\views.py, в котором на первом этапе мы записали тестовый контент. Для обработки реального контента из модели Post код должен выглядеть так.
Чтобы модель для создания новых записей отображалась в панели администрирования, ее нужно зарегистрировать в файле blog\admin.py:
from django.contrib import admin from .models import Post admin.site.register(Post)
Теперь можно открыть админку http://localhost:8000/admin/ и создать несколько постов от разных пользователей:
Обратите внимание на формат даты – если указание часов и минут не требуется, формат можно изменить в шаблоне home.html:
<small class="text-muted">{{ post.date_posted|date:"F d, Y" }}</small>
Формы регистрации и авторизации
Как уже упоминалось, приложения из проекта можно использовать отдельно – вставить блог, например, в другой проект. Поэтому и систему регистрации / авторизации стоит реализовать отдельно. Запустим Джанго-команду для создания нового приложения под названием users: python manage.py startapp users
. После этого нужно зарегистрировать новое приложение, как мы уже делали с блогом. Сначала откройте my_site\settings.py и добавьте нужную строку в список INSTALLED_APPS
:
INSTALLED_APPS = [ 'blog.apps.BlogConfig', 'users.apps.UsersConfig', 'crispy_forms', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
В этом же файле в самом низу добавьте ссылку на стили Bootstrap для форм:
CRISPY_TEMPLATE_PACK = 'bootstrap4'
Модуль django-crispy-forms не входит в стандартный дистрибутив Джанго – скорее всего, вам потребуется его установить: pipenv install django-crispy-forms
.
Затем откройте users\views.py и сохраните в нем код:
from django.shortcuts import render, redirect from django.contrib import messages from .forms import UserRegisterForm def register(request): if request.method == 'POST': form = UserRegisterForm(request.POST) if form.is_valid(): form.save() username = form.cleaned_data.get('username') messages.success(request, f'Создан аккаунт {username}!') return redirect('blog-home') else: form = UserRegisterForm() return render(request, 'users/register.html', {'form': form})
Для формы регистрации нам потребуется соответствующий шаблон. Как и в случае с блогом, создайте в папке users директорию templates, в ней – поддиректорию users, а в ней файл register.html. Код шаблона будет таким.
Внесем нужные изменения в url-паттерны. Откройте my_site\urls.py и добавьте в него импорт users_views
и маршрут к форме регистрации:
from django.contrib import admin from django.urls import path, include from users import views as user_views urlpatterns = [ path('admin/', admin.site.urls), path('register/', user_views.register, name='register'), path('', include('blog.urls')), ]
Теперь создайте файл users\forms.py и сохраните в нем этот код, после чего добавьте отображение сообщения об успешной регистрации в шаблон блога base.html, прямо над блоком контента {% block content %}{% endblock %}
:
{% if messages %} {% for message in messages %} <div class="alert alert-{{ message.tags }}"> {{ message }} </div> {% endfor %} {% endif %}
Запустим python manage.py runserver и оценим нашу форму регистрации http://localhost:8000/register/:
Зарегистрируем нового пользователя NewUser и получим сообщение об успешной регистрации аккаунта. Проверим панель администрирования http://localhost:8000/admin/auth/user/ – новая учетная запись там появилась, значит, форма работает правильно. Попробуйте ввести некорректные регистрационные данные – форма проводит валидацию самостоятельно, без всяких дополнительных усилий с нашей стороны:
Вход и доступ к профилям для зарегистрированных пользователей
Одно из главных преимуществ системы авторизации – возможность показывать определенный контент только зарегистрированным пользователям. Сначала мы создадим логику и страницы входа и выхода, а затем перейдем к вопросу ограничения доступа для неавторизованных и/или незарегистрированных пользователей.
Прежде всего добавим в файл my_site\urls.py импорт нужных модулей и маршруты к шаблонам страниц входа и выхода. Теперь нужно создать два шаблона в папке users. Сохраните этот код для login.html. Он генерирует такую страницу:
Код для logout.html генерирует страницу выхода из учетной записи:
Внизу файла my_site\settings.py добавьте:
LOGIN_REDIRECT_URL = 'blog-home' LOGIN_URL = 'login'
Также отредактируем код в файле users\views.py, теперь он должен выглядеть так.
Чтобы управлять профилями в админ-панели, нужно зарегистрировать модель в admin.py:
from django.contrib import admin from .models import Profile admin.site.register(Profile)
Создайте шаблон для страницы профиля – profile.html в templates/users, и сохраните этот код в users\models.py. Код модели использует библиотеку для работы с изображениями Pillow. Установите ее в виртуальное окружение проекта: pipenv install pillow
. Создайте и примените миграции:
python manage.py makemigrations python manage.py migrate
Теперь можно запускать сервер – у нас уже есть работающие страницы http://localhost:8000/login/ и http://localhost:8000/logout/; на страницу login выполняется переадресация после регистрации. Если сейчас ввести некорректный логин, появится сообщение об ошибке. Но и ввод верных данных приведет к ошибке 404 – приложение пытается открыть профиль пользователя, но у него пока что нет правильного маршрута к странице. На самом деле, и переадресация на профиль после входа на сайт выглядит странно – гораздо логичнее перенаправить пользователя на главную страницу блога, что мы и сделаем.
Займемся переадресацией – откроем my_site\settings.py и добавим переадресацию в конце файла:
LOGIN_URL = 'login'
Теперь, если вы введете верный логин и пароль, произойдет переадресация на главную страницу блога. Пока что визуально это не слишком очевидно – ссылки на панели навигации не соответствуют тому, вошел ли пользователь на сайт или нет – но мы сейчас это исправим.
Прежде всего, внесем изменения в шаблон base.html – найдите правый блок навигации и вставьте этот код между тегами <div class="navbar-nav"></div>
:
{% if user.is_authenticated %} <a class="nav-item nav-link" href="{% url 'profile' %}">Профиль</a> <a class="nav-item nav-link" href="{% url 'logout' %}">Выход</a> {% else %} <a class="nav-item nav-link" href="{% url 'login' %}">Вход</a> <a class="nav-item nav-link" href="{% url 'register' %}">Регистрация</a> {% endif %}
Если зайти на сайт с правильным логином и паролем, можно увидеть свой профиль – правда, пока без аватарки:
Последнее, что мы сделаем на этом этапе – обеспечим ограничение доступа к профилям для незарегистрированных пользователей. Для этого в файл users\views.py нужно добавить декоратор @login_required
:
@login_required def profile(request): return render(request, 'users/profile.html')
Если неавторизованный пользователь теперь попытается открыть страницу профиля, он будет переадресован на страницу входа на сайт. Напоминаем: весь код, созданный на этом этапе работы, находится здесь.
Промежуточные итоги
В этой части туториала мы реализовали систему авторизации в виде отдельного приложения, которое в дальнейшем можно будет использовать в любом другом Django-проекте. Дополнительной функциональностью для управления профилями мы займемся в следующей, заключительной части.