Что такое миксины?
Как мы уже знаем, как два представления Django на основе классов построены из миксинов, которые обеспечивают изолированную функциональность. Они позволяют объединить общие функциональности и методы в одном классе, который затем можно использовать в других классах или моделях. Миксины добавляют дополнительные возможности и функционал к нашим классам, без необходимости повторного написания кода.
Мы рассмотрим, DetailView кто создает подробное представление объекта и ListView кто создает список объектов, обычно из набора запросов, с необязательной разбивкой на страницы. Это приведет нас к рассмотрению четырех миксинов, которые в сочетании обеспечивают полезную функциональность при обработке одного объекта Django или набора объектов.
Существуют также классы миксинов и в общих представлениях редактирования ( FormView и представлениях CreateView , UpdateView и DeleteView ).
Стандартные миксины Django
Для безопасности проекта мы можем использовать встроенные миксины, которые запрещают неавторизованным пользователям добавлять материал. На этот случай в Django существует миксин LoginRequiredMixin, который дает возможность добавлять материалы только после авторизации пользователя на сайте.
В разделе 10.9 "Работа с CreateView" мы реализовали добавление статьи с помощью представления CreateView. Давайте наше представление дополним, добавив в него миксин LoginRequiredMixin.
from django.contrib.auth.mixins import LoginRequiredMixin
class PostCreateView(LoginRequiredMixin, CreateView):
"""
Представление: создание материалов на сайте
"""
model = Post
template_name = 'blog/post_create.html'
form_class = PostCreateForm
login_url = 'home'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'Добавление статьи на сайт'
return context
def form_valid(self, form):
form.instance.author = self.request.user
form.save()
return super().form_valid(form)
По сути, мы "подмешали" миксин к классу CreateView, дополнив код представления как под капотом, так и добавили свойство для ссылки авторизации пользователя, так как у нас пока нет авторизации, мы будем перенаправлять пользователя на главную страницу сайта.
Давайте проверим в деле, как это работает. Запустим сервер и через админ панель выйдем из аккаунта. Теперь попробуем добавить статью, перейдя по следующему адресу: http://127.0.0.1:8000/post/create/. Автоматически, меня перебрасывает на страницу всех статей со статусом HTTP 302.
В консоли Django мы увидим следующее:
[26/Nov/2023 14:19:08] "GET /post/create/ HTTP/1.1" 302 0
А в браузере мы будем перенаправлены по адресу http://127.0.0.1:8000/?next=/post/create/
Рассмотрим миксин уведомления для представления обновления материала. Для этого мы будем использовать встроенный миксин SuccessMessageMixin при отправке формы.
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin
class PostUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
"""
Представление: обновления материала на сайте
"""
model = Post
template_name = 'blog/post_update.html'
context_object_name = 'post'
form_class = PostUpdateForm
login_url = 'home'
success_message = 'Запись была успешно обновлена!'
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = f'Обновление статьи: {self.object.title}'
return context
def form_valid(self, form):
# form.instance.updater = self.request.user
form.save()
return super().form_valid(form)
В примере выше мы использовали два миксина, один для неавторизованных пользователей, и один для уведомления при успешном обновлении материала, также этот миксин можно добавить и к представления добавления материала.
Нам необходимо настроить шаблон уведомления, для этого в папке templates создадим папку includes, и в нее добавим шаблон messages.html со следующим кодом:
{% if messages %}
{% for message in messages %}
<div class="alert alert-{% if message.tags %}{{ message.tags }}{% endif %} alert-dismissible fade show" role="alert">
<i class="fas fa-info-circle"></i> {{message}}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endif %}
Шаблон мы используем из Bootstrap, а сами теги из документации по django.contrib.messages
Далее нам необходимо подключить компонент messages в main.html, поэтому обновляем содержимое:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
crossorigin="anonymous"></script>
</head>
<body>
{% include 'header.html' %}
<div class="container">
<div class="row">
<div class="col-lg-8 p-4">
{% include 'includes/messages.html' %}
{% block content %}
{% endblock %}
{% include 'pagination.html' %}
</div>
<div class="col-4 p-4">
{% include 'sidebar.html' %}
</div>
</div>
</div>
{% include 'footer.html' %}
</body>
</html>
Отлично, теперь давайте обновим одну из наших статей и посмотрим как работает миксин уведомления. Запустим сервер, перейдем в панель администратора и авторизуемся. Далее откроем http://127.0.0.1:8000 и перейдем в любую запись. И в адресной строке добавим /update/ к пути.
Обновив запись мы увидим следующее сообщение:
Мы видим что все прекрасно работает, в следующем шаге мы попробуем добавить кастомный миксин, с помощью которого редактировать записи сможет только администратор или автор записи.