add: приложение blog (для страниц и постов)
This commit is contained in:
93
etpgrf_site/blog/models.py
Normal file
93
etpgrf_site/blog/models.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.urls import reverse
|
||||
|
||||
class PostType(models.TextChoices):
|
||||
BLOG = 'B', 'Пост в блог'
|
||||
PAGE = 'P', 'Страница'
|
||||
|
||||
class Post(models.Model):
|
||||
"""
|
||||
Модель для постов блога и статических страниц.
|
||||
"""
|
||||
title = models.CharField(
|
||||
verbose_name="Заголовок",
|
||||
max_length=255,
|
||||
help_text="Основной заголовок (H1). Обязательно для заполнения."
|
||||
)
|
||||
slug = models.SlugField(
|
||||
verbose_name="URL (slug)",
|
||||
max_length=255,
|
||||
unique=True,
|
||||
help_text="Уникальная часть адреса. Используйте латиницу, цифры и дефис. Например: my-new-post"
|
||||
)
|
||||
|
||||
post_type = models.CharField(
|
||||
verbose_name="Тип публикации",
|
||||
max_length=1,
|
||||
choices=PostType.choices,
|
||||
default=PostType.BLOG,
|
||||
help_text="Страница доступна по адресу /slug/, Пост — по адресу /blog/slug/"
|
||||
)
|
||||
|
||||
is_published = models.BooleanField(
|
||||
verbose_name="Опубликовано",
|
||||
default=True,
|
||||
help_text="Снимите галочку, чтобы скрыть публикацию (черновик)."
|
||||
)
|
||||
published_at = models.DateTimeField(
|
||||
verbose_name="Дата публикации",
|
||||
default=timezone.now,
|
||||
help_text="Дата, которая будет отображаться в блоге. Можно запланировать на будущее."
|
||||
)
|
||||
|
||||
content = models.TextField(
|
||||
verbose_name="Контент",
|
||||
help_text="Основной текст публикации. Поддерживает HTML."
|
||||
)
|
||||
excerpt = models.TextField(
|
||||
verbose_name="Краткое описание (тизер)",
|
||||
blank=True,
|
||||
help_text="Отображается в списке постов. Если оставить пустым, будет взято начало контента."
|
||||
)
|
||||
|
||||
image = models.ImageField(
|
||||
verbose_name="Обложка",
|
||||
upload_to='blog/',
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="Изображение для превью в ленте и Open Graph (соцсети)."
|
||||
)
|
||||
|
||||
# SEO
|
||||
seo_title = models.CharField(
|
||||
verbose_name="SEO Title",
|
||||
max_length=255,
|
||||
blank=True,
|
||||
help_text="Заголовок для поисковиков (<tt><title></tt>). Если пусто, используется основной заголовок."
|
||||
)
|
||||
seo_description = models.TextField(
|
||||
verbose_name="SEO Description",
|
||||
blank=True,
|
||||
help_text="Описание для поисковиков (meta description). Рекомендуется 150-160 символов."
|
||||
)
|
||||
seo_keywords = models.CharField(
|
||||
verbose_name="SEO Keywords",
|
||||
max_length=255,
|
||||
blank=True,
|
||||
help_text="Ключевые слова через запятую (meta keywords). Сейчас почти не используется поисковиками,"
|
||||
"но может пригодиться."
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Публикация"
|
||||
verbose_name_plural = "Публикации"
|
||||
ordering = ['-published_at']
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
def get_absolute_url(self):
|
||||
if self.post_type == PostType.PAGE:
|
||||
return reverse('page_detail', kwargs={'slug': self.slug})
|
||||
return reverse('post_detail', kwargs={'slug': self.slug})
|
||||
Reference in New Issue
Block a user