ContentType в Django

Управление контентом в Django: создание гибкой системы баннеров

Django предоставляет приложение contenttypes, которое позволяет отслеживать все модели, установленные в вашем проекте, и обеспечивает высокоуровневый, общий интерфейс для работы с вашими моделями.

Основные принципы

В основе приложения contenttypes лежит модель ContentType, которая представляет собой информацию о моделях, установленных в вашем проекте. Экземпляры ContentType автоматически создаются каждый раз, когда создаются новые модели.

Что такое ContentType?

ContentType является экземпляром модели ContentType, которая хранит информацию о типе содержимого. Это включает в себя:

  • app_label: название приложения, к которому принадлежит тип содержимого
  • model: название модели, к которой принадлежит тип содержимого

Для чего нужен ContentType?

ContentType нужен для нескольких целей:

  1. Управление содержимымContentType позволяет управлять содержимым в базе данных, определяя тип данных, которые хранятся в каждой таблице.
  2. Связь между моделямиContentType позволяет связывать модели между собой, определяя тип содержимого, которое они представляют.
  3. Динамическое создание моделейContentType позволяет создавать модели динамически, без необходимости определять их заранее.
  4. Generic foreign keysContentType позволяет использовать generic foreign keys, которые могут ссылаться на любую модель в базе данных.

Пример использования ContentType

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

Код

from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models import When, Case, Q
from django.utils.translation import gettext_lazy as _


class ContentTypeProxy(ContentType):
    """Для сортировки баннеров по приоритету"""
    
    class Meta:
        proxy = True
        ordering = [
            Case(
                When(model='bannerhorizontal', then=1),
                When(app_label='events', model='event', then=2),
                When(app_label='clubs', model='club', then=3),
                When(app_label='styles', model='style', then=4),
                When(app_label='musicians', model='musician', then=5),
                When(app_label='photoblogs', model='photoblog', then=6),
                When(app_label='albums', model='album', then=7),
                When(app_label='festivals', model='festival', then=8),
                When(app_label='instruments', model='instrument', then=9),
                When(app_label='learnings', model='learning', then=10),
                default=11
            )
        ]

    def __str__(self):
        """Для вывода нужных названий баннеров в админке"""
        if self.app_label == "general" and self.model == "bannerhorizontal":
            return str(_("Main"))
        if self.app_label == "events" and self.model == "event":
            return str(_("Poster"))
        if self.app_label == "clubs" and self.model == "club":
            return str(_("Clubs"))
        if self.app_label == "styles" and self.model == "style":
            return str(_("Styles"))
        if self.app_label == "musicians" and self.model == "musician":
            return str(_("People"))
        if self.app_label == "photoblogs" and self.model == "photoblog":
            return str(_("Photo blog"))
        if self.app_label == "albums" and self.model == "album":
            return str(_("Albums"))
        if self.app_label == "festivals" and self.model == "festival":
            return str(_("Festivals"))
        if self.app_label == "instruments" and self.model == "instrument":
            return str(_("Instruments"))
        if self.app_label == "learnings" and self.model == "learning":
            return str(_("Learnings"))
        return super().__str__()


class BannerHorizontal(models.Model):
    """Banner"""
    
    ADVERT_APPS = (
            Q(app_label="general", model="bannerhorizontal")
            | Q(app_label="events", model="event")
            | Q(app_label="clubs", model="club")
            | Q(app_label="styles", model="style")
            | Q(app_label="musicians", model="musician")
            | Q(app_label="photoblogs", model="photoblog")
            | Q(app_label="albums", model="album")
            | Q(app_label="festivals", model="festival")
            | Q(app_label="instruments", model="instrument")
            | Q(app_label="learnings", model="learning")
    )

    name = models.CharField(_("Name"), max_length=50)
    under_name = models.CharField(_("Under name"), max_length=50, blank=True)
    logo = models.FileField(_("Logo"), upload_to="banners/")
    link = models.URLField(_("Link"), blank=True, null=True)
    content_type = models.ManyToManyField(
        ContentTypeProxy,
        verbose_name=_("Show on pages"),
        limit_choices_to=ADVERT_APPS,
        related_name="banners",
    )
    published = models.BooleanField(_("Published"), default=False)
    sort = models.IntegerField(_("Sort"), default=0)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = _("Banner horizontal")
        verbose_name_plural = _("Banners horizontal")
        ordering = ("sort",)

Этот код представляет собой часть Django-приложения, которое управляет баннерами на сайте. Баннеры могут быть показаны на различных страницах сайта, и этот код позволяет управлять этими баннерами и их местоположением.

ContentTypeProxy

Первый класс, ContentTypeProxy, является прокси-моделью для ContentType из Django. ContentType - это модель, которая хранит информацию о всех моделях в проекте. Прокси-модель позволяет нам добавить дополнительную логику к ContentType без изменения исходного кода Django.

В этом случае мы добавляем метод __str__, который возвращает строковое представление ContentType. Это позволяет нам показать более понятные названия для каждого ContentType в админке Django.

Мы также добавляем поле ordering, которое определяет порядок, в котором будут показаны ContentType в админке. В этом случае мы используем Case и When из Django, чтобы определить порядок на основе имени модели и приложения.

BannerHorizontal

Второй класс, BannerHorizontal, представляет собой модель баннера. Баннер имеет следующие поля:

  • name: название баннера
  • under_name: подзаголовок баннера
  • logo: логотип баннера
  • link: ссылка на баннер
  • content_type: поле ManyToMany, которое связывает баннер с ContentTypeProxy. Это позволяет нам показывать баннер на различных страницах сайта.
  • published: флаг, который показывает, опубликован ли баннер
  • sort: поле, которое определяет порядок показа баннеров

Мы также добавляем метод __str__, который возвращает название баннера.

ADVERT_APPS

Переменная ADVERT_APPS представляет собой кортеж Q-объектов, которые определяют приложения и модели, которые могут быть связаны с баннером. Это позволяет нам ограничить выбор ContentType в админке Django.

Использование

Этот код можно использовать в админке Django для управления баннерами и их местоположением. Например, мы можем создать баннер и выбрать страницы, на которых он будет показан, используя поле content_type. Мы также можем изменить порядок показа баннеров, используя поле sort.

В целом, этот код позволяет нам управлять баннерами на сайте и показывать их на различных страницах, используя ContentType из Django.

Read more

Использование Email вместо имени пользователя для входа в Django Admin

По умолчанию, Django использует имя пользователя для входа в систему. Однако, в некоторых случаях использование email может быть более удобным и практичным. Например, большинство пользователей помнят свой email, а не имя пользователя. В этой статье мы рассмотрим, как настроить вход в Django с использованием email вместо имени пользователя. Зачем использовать

By Dmitry

Показ кастомной страницы 404 в Django

В этом посте мы рассмотрим, как показать кастомную страницу 404 в приложении на Django. Это может быть полезно, если вы хотите предоставить пользователям более информативную и дружелюбную страницу ошибки вместо стандартной страницы 404, которая показывает только сообщение об ошибке. Шаг 1: Создание кастомной страницы 404 Сначала создайте новый шаблон для

By Dmitry

Вход по SSH на удаленный сервер Ubuntu без пароля

Настройка входа по SSH на сервере Ubuntu В этой статье мы рассмотрим, как настроить вход пользователей только по SSH на сервере Ubuntu. Это позволит повысить безопасность вашего сервера, ограничив вход только по защищённому протоколу SSH. Шаг 1: Установка и настройка OpenSSH OpenSSH - это пакет, который позволяет устанавливать защищённое соединение

By Dmitry

Автоматизация деплоя по SSH с паролем

Автоматизация деплоя с помощью GitHub Actions и SSH для Django проекта (вход на сервер по SSH с паролем) GitHub Actions — это сервис, который позволяет автоматизировать процесс сборки, тестирования и деплоя вашего кода. Одним из способов деплоя является использование SSH для подключения к серверу и копирования файлов. В этой статье мы

By Dmitry