Skip to content

Latest commit

 

History

History
132 lines (94 loc) · 12.1 KB

Урок 8: Пользователи и сессии.md

File metadata and controls

132 lines (94 loc) · 12.1 KB

Вступление

Вы уже успели поработать с Моделями, обычными и классовыми Вью, Шаблонами и все это было встроено в Джанго. В других фреймворках редко все это встречается из коробки. Там нужно устанавливать их через сторонние библиотеки и отдельно настраивать.

Еще одна вещь, которая обычно не встроена в фреймворки, но есть в Джанго — Пользователи.

Пользователи

Это очень мощная система, состоящая из множества частей. Туда входит авторизация, регистрация, права (ограничения), администрирование, и сессии.

Встроенные Вью

В каждом новом Джанго проекте изначально устанавливается приложение auth — вы можете увидеть его среди INSTALED_APPS в файле настроек. Именно поэтому вы могли заметить в админке пункты Пользователи и Группы.

Приложение auth добавлет в наш проект объект пользователя с полями: username, password, email, first_name, last_name. В Джанго также встроены классовые Вью для аутентификации: LoginView, LogoutView и другие.

Самый простой способ подключить их — добавить в наш urls.py сразу все встроенные URL:

urlpatterns = [
   path('accounts/', include('django.contrib.auth.urls')),
]

Полный список встроенных Вью и ссылок на них

Все эти ссылки автоматически заработают. Но мы все равно увидим ошибку — Джанго потребует шаблоны для этих вью и будет по дефолту искать их в директории templates/registration. К примеру такой шаблон потребуется для формы авторизации:

templates/registration/login.html

<h2>Login</h2>
	<form method="post">  
	{% csrf_token %} 
	{{ form.as_p }} 
	<button type="submit">Login</button>
</form>

Все остальное Джанго сделает сама. Вы можете ввести в такую форму данные от своего аккаунта суперюзера. Нас перекинет на несуществующую страницу профиля. Чтобы изменить редирект после успешной авторизации можно в settings.py задать другой: LOGIN_REDIRECT_URL = '/', а для успешного выхода LOGOUT_REDIRECT_URL.

Информация о каждом авторизованном пользователе хранится в сессии. Про них мы подробнее поговорим позже. Благодаря сессии мы можем из любого запроса узнать авторизован ли пользователь. С каждым запросом передаются вообще все поля модели пользователя.

Добавим в наш шаблон код, который выведет кнопку для входа. А если пользователь уже авторизован, то напишем его ник и выведем кнопку для выхода:

{% if user.is_authenticated %} 
	<p>Привет, {{ user.username }}!</p>
	<p><a href="{% url 'logout' %}">Выйти</a></p>
{% else %} 
	<p>You are not logged in.</p>
	<a href="{% url 'login' %}">Войти</a> 
{% endif %}

Объект user автоматически передается в контекст любого шаблона. Через него мы можем узнать авторизован ли пользователь, администратор ли он, вывести поля модели.

Регистрация

С авторизацией разобрались, но как пользователю завести новый аккаунт? Джанго не дает нам такой же удобной ссылки для авторизации. Но в нее встроена UserCreationForm. Так может выглядеть Вью для регистрации пользователя. Добавьте его самостоятельно:

from django.contrib.auth.forms import UserCreationForm 
from django.urls import reverse_lazy 
from django.views import generic

class SignUpView(generic.CreateView): 
    form_class = UserCreationForm 
    success_url = reverse_lazy('login') 
    template_name = 'signup.html'

Сессии

Это мощный инструмент для хранения информации о пользователе. На самом деле сессию можно рассматривать как Питоновский словарь. В нее можно добавлять по ключу любые значения и также вытаскивать их через вью.

Она передается с каждым запросом и её можно получить через request.session. Обычно в сессии хранится информация о поведении пользователя на сайте. Дата последнего визита или количество визитов. Также благодаря сессиям нас не разглогинивает из сайтов после закрытия вкладки.

Внутри сессии используют браузерные куки-файлы. Вы можете посмотреть их через браузер, откройте наш сайт и найдете там ID сессии и свой CSRF-токен. По ID из куки-файла наш сайт понимает, что за пользователь перед ним и может вывести ник или профиль.

Помимо сессии из request можно напрямую получить профиль пользователя. Он будет передаваться в любом запросе, который делается на нашем сайте. Его мы можем получить через request.user

Например, мы можем получить пользователя при валидации формы:

def form_valid(self, form): 
    product = Product.objects.get(id=self.kwargs['pk']) 
    user = self.request.user 
    form.instance.user = user 
    form.instance.product = product 
    return super().form_valid(form)

Чтобы этот код работал и в заказ сохранялся еще и объект пользователя — нам нужно добавить в модель заказа ForeignKey на пользовательскую модель. Не забудьте сделать его необязательным, иначе мы будем получать ошибки при незалогиненном пользователе. А что если мы хотим сделать, чтобы заказы мог делать только авторизованный пользователь?

Документация сессий

Миксины

Тут нам поможет еще одна фишка наследования в Python — миксин. Один класс может наследоваться от нескольких других. Поэтому можно использовать родительские классы для добавления свойств дочернему классу.

Миксин дает лишь примесь логики для всей конструкции, он не описывает ее целиком. Мы можем использовать LoginRequiredMixin. Он будет применяться к нашему Вью и как можно догадаться из названия сделает обязательным авторизацию для его просмотра.

from django.contrib.auth.mixins import LoginRequiredMixin

class OrderFormView(LoginRequiredMixin, generic.CreateView):
	...

Миксин обязательно передается первым параметром. Потому что наследование в Джанго идет справа налево, а он всего-лишь примесь логики и должен применяться последним.

Теперь при открытии формы заказа незалогиненным нас будет автоматически перенаправлять на форму авторизации. Магия!

А что если мы хотим сделать страницу только для админов? Тут нам понадобится другой миксин UserPassesTestMixin. Там мы можем сами написать любое условие и проверить соответствует ли ему пользователь.

from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
    
 # наш секретный Вью
class SecretAdminView(UserPassesTestMixin, generic.TemplateView):
	# секретное содержимое
  template_name = 'memes.html'
	# проверяем условие, если пользователь — админ, то вернет True и пустит пользователя
	def test_func(self): 
	  return self.request.user.is_superuser

Теперь никто не узнает, чем на самом деле занимаются админы. На самом деле спектр фильтров здесь огромный. Например, можно пускать только пользователей с датой регистрации более трех лет назад — такой вот раздел для олдфагов. Также можно фильтровать пользователей при помощи прав.

Документация наших Миксинов

Права

Также в Джанго встроена гибкая система прав. Вы можете назначить любому пользователю возможность совершать любое малейшее изменение на сайте. Вы можете добавлять права по одному или через группы. Например сделать группу модераторов и разрешить им только редактировать фотографии товаров.

Права и группы можно выдавать через админку. Вы можете также делать свои кастомные права и проверять на них пользователей.

Документация прав и пользователй

Итоги

Мы узнали, как поднять авторизацию и регистрацию на нашем сайте. В очередной раз убедились, что в Джанго встроено все что можно. Научились защищать нашу страницу от доступа незалогиненных пользователей и делать страницы только для админов.