Курс по Django: https://stepik.org/a/183363
Архив проекта: 63_sitewomen.zip
На данный момент
мы с вами научились авторизовывать существующих пользователей на сайте. Но что
нам это сейчас дает? Все страницы сайта как были открытыми для посетителей, так
и остаются в открытом виде. Давайте добавим ограничения на некоторые из них.
Начнем с функций
представлений. В файле women/views.py у нас имеется
такая подходящая функция с именем about(), которая
отвечает за страницу «О сайте». Чтобы закрыть ее от неавторизованных
пользователей, достаточно декорировать ее декоратором login_required следующим
образом:
@login_required
def about(request):
...
Если теперь
запустить веб-сервер и попытаться перейти на эту страницу неавторизованному
пользователю, то выполнится автоматическое перенаправление по адресу:
http://127.0.0.1:8000/accounts/login/?next=/about/
Обратите
внимание на появление параметра next. Благодаря ему, после успешной
авторизации мы сразу перейдем к закрытой странице «О сайте». Но на данный
момент у нас другая проблема. Фреймворк Django выполняет
автоматическое перенаправление по несуществующему URL-адресу.
Поправить это очень просто. Вспомним об еще одном параметре LOGIN_URL, который
определяет адрес страницы с формой авторизации. В файле settings.py
пропишем
его следующим образом:
LOGIN_URL = 'users:login'
Теперь, при
заходе на страницу «О сайте» нам открывается форма авторизации. И фреймворк Django автоматически
добавляет к URL-адресу параметр
next. Вводим верные
логин/пароль. И заветная страница отображается в браузере пользователя. Вот так
с помощью декоратора login_required можно ограничивать доступ к отдельным
страницам сайта.
Другой вариант
перенаправления при доступе к закрытой странице можно определять с помощью
параметра login_url самого декоратора:
@login_required(login_url='/admin/')
…
Произойдет
перенаправление к старице админ-панели. Причем, приоритет этого параметра выше,
чем LOGIN_URL.
Класс миксин LoginRequiredMixin
Когда мы имеем
дело с классами представлений, то здесь вместо декоратора login_required
используется класс минксинов LoginRequiredMixin. О миксинах мы с вами уже
говорили, когда создавали свой класс DataMixin. В данном случае LoginRequiredMixin
добавляет новый функционал к классу представления, ограничивая доступ к
странице неавторизованным пользователям. Давайте его пропишем для класса AddPage,
предполагая, что новые статьи могут добавлять только зарегистрированные
пользователи:
class AddPage(LoginRequiredMixin, DataMixin, CreateView):
...
Теперь, при
попытке открыть эту страницу стороннему посетителю, будет выполнено
перенаправление на форму авторизации. URL-адрес этой формы также будет
содержать параметр next. После ввода логина/пароля попадаем на страницу
добавления статьи.
Если нам нужно в
классе представления определить свой URL-адрес перехода для
неавторизованных пользователей, то достаточно прописать атрибут login_url,
например, так:
При обращении к
закрытой странице выполнится перенаправление на админ-панель. И так можно ограничивать
доступ к любым страницам сайта. (Уберем этот последний параметр.)
Добавление авторства статей
Раз уж мы с вами
сделали ограничение доступа к странице добавления статей, то было бы логично с
каждой статьей связать своего автора. Для этого в модели Women мы добавим еще
одно поле в виде связи многие к одному следующим образом:
author = models.ForeignKey(get_user_model(), on_delete=models.SET_NULL, related_name='posts', null=True, default=None)
Обратите
внимание, мы обращаемся к модели User с помощью функции get_user_model(). Это
считается предпочтительной практикой для фреймворка Django. Далее,
прописываем параметр on_delete с флагом SET_NULL, то есть, при
удалении пользователя поле author будет содержать
значение NULL. Остальные
параметры вам уже хорошо известны.
Так как модель
изменилась, то нам нужно создать и применить миграции:
python manage.py
makemigrations
python manage.py
migrate
Все, таблица women обновлена и в
ней появилось новое поле author_id со значениями NULL.
Осталось только
заполнять это поле в момент добавления статьи. Для этого перейдем в файл women/views.py и в класс AddPage
добавим метод form_valid():
def form_valid(self, form):
w = form.save(commit=False)
w.author = self.request.user
return super().form_valid(form)
Смотрите, мы
здесь обращаемся к форме и вызываем у нее метод save() с параметром commit=False. Благодаря ему
данные не записываются в таблицу БД, а формируются только в памяти. В
результате ссылка w будет указывать на объект модели Women текущей записи.
Меняем в этом объекте атрибут author, присваивая ему объект user текущего
пользователя. Далее, измененный объект w будет
автоматически сохранен в таблице БД.
Посмотрим, как
это будет работать. Откроем страницу добавления записи. Введем произвольные
данные и видим, что в поле author_id таблицы women появилось
значение 1. Это как раз идентификатор авторизованного суперпользователя.
Ну и раз у нас
каждая статья связана с пользователем, то отобразим его username в списке
статей. Откроем файл index.html и изменим
строчку при отображении названий категорий:
<p class="first">Категория: {{p.cat.name}} | автор: {{p.author.username|default:"неизвестен"}}</p>
Теперь на
странице дополнительно отображается ее автор, если он известен.
Курс по Django: https://stepik.org/a/183363