🐍🚀 Django с нуля. Часть 2: регистрация, авторизация, ограничение доступа

Во второй части туториала будем разрабатывать систему регистрации и авторизации, а также ограничим доступ к просмотру профилей для неавторизованных посетителей блога.
🐍🚀 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-проекте. Дополнительной функциональностью для управления профилями мы займемся в следующей, заключительной части.

***

Материалы по теме

МЕРОПРИЯТИЯ

Комментарии

ВАКАНСИИ

Добавить вакансию
C# Developer
Москва, по итогам собеседования
Backend Lead (Python, Django)
по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ