ContentType в Django
Управление контентом в Django: создание гибкой системы баннеров
Django предоставляет приложение contenttypes
, которое позволяет отслеживать все модели, установленные в вашем проекте, и обеспечивает высокоуровневый, общий интерфейс для работы с вашими моделями.
Основные принципы
В основе приложения contenttypes
лежит модель ContentType
, которая представляет собой информацию о моделях, установленных в вашем проекте. Экземпляры ContentType
автоматически создаются каждый раз, когда создаются новые модели.
Что такое ContentType?
ContentType
является экземпляром модели ContentType
, которая хранит информацию о типе содержимого. Это включает в себя:
app_label
: название приложения, к которому принадлежит тип содержимогоmodel
: название модели, к которой принадлежит тип содержимого
Для чего нужен ContentType?
ContentType
нужен для нескольких целей:
- Управление содержимым:
ContentType
позволяет управлять содержимым в базе данных, определяя тип данных, которые хранятся в каждой таблице. - Связь между моделями:
ContentType
позволяет связывать модели между собой, определяя тип содержимого, которое они представляют. - Динамическое создание моделей:
ContentType
позволяет создавать модели динамически, без необходимости определять их заранее. - Generic foreign keys:
ContentType
позволяет использовать 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.