schon/engine/blog/models.py
Egor fureunoir Gorbunov 13e7af52aa Features: 1) Improved request processing in middleware by adding mutable QueryDict implementation; 2) Extended type annotations across various modules for enhanced type safety; 3) Refined JWT token lifetime configuration for environment-specific logic.
Fixes: 1) Addressed missing or incorrect imports and type hints with `# ty:ignore` markers; 2) Fixed search queryset error handling in filters module; 3) Resolved issues in viewsets with updated `@action` method usage.

Extra: Removed unused classes and dependencies (e.g., `BaseMutation`, `basedpyright`, and related packages); streamlined GraphQL mutation implementations; cleaned up unused arguments in model `save` methods.
2025-12-19 15:17:17 +03:00

159 lines
5.1 KiB
Python

from django.conf import settings
from django.db.models import (
CASCADE,
BooleanField,
CharField,
FileField,
ForeignKey,
ManyToManyField,
)
from django.utils.translation import gettext_lazy as _
from django_extensions.db.fields import AutoSlugField
from markdown.extensions.toc import TocExtension
from markdown_field import MarkdownField
from engine.core.abstract import NiceModel
class Post(NiceModel):
__doc__ = _( # pyright: ignore[reportUnknownVariableType]
"Represents a blog post model. "
"The Post class defines the structure and behavior of a blog post. "
"It includes attributes for author, title, content, optional file attachment, slug, and associated tags. "
"The class enforces constraints such as requiring either content or a file attachment but not both simultaneously. "
"It also supports automatic slug generation based on the title."
)
is_publicly_visible = True
author = ForeignKey(
to=settings.AUTH_USER_MODEL,
on_delete=CASCADE,
blank=False,
null=False,
related_name="posts",
)
title = CharField(
unique=True,
max_length=128,
blank=False,
null=False,
help_text=_("post title"),
verbose_name=_("title"),
)
content: MarkdownField = MarkdownField(
"content",
extensions=[
TocExtension(toc_depth=3),
"pymdownx.arithmatex",
"pymdownx.b64",
"pymdownx.betterem",
"pymdownx.blocks.admonition",
"pymdownx.blocks.caption",
"pymdownx.blocks.definition",
"pymdownx.blocks.details",
"pymdownx.blocks.html",
"pymdownx.blocks.tab",
"pymdownx.caret",
"pymdownx.critic",
"pymdownx.emoji",
"pymdownx.escapeall",
"pymdownx.extra",
"pymdownx.fancylists",
"pymdownx.highlight",
"pymdownx.inlinehilite",
"pymdownx.keys",
"pymdownx.magiclink",
"pymdownx.mark",
"pymdownx.pathconverter",
"pymdownx.progressbar",
"pymdownx.saneheaders",
"pymdownx.smartsymbols",
"pymdownx.snippets",
"pymdownx.striphtml",
"pymdownx.superfences",
"pymdownx.tasklist",
"pymdownx.tilde",
],
blank=True,
null=True,
)
file = FileField(upload_to="posts/", blank=True, null=True)
slug = AutoSlugField(
populate_from="title", allow_unicode=True, unique=True, editable=False
)
tags = ManyToManyField(to="blog.PostTag", blank=True, related_name="posts")
meta_description = CharField(max_length=150, blank=True, null=True)
is_static_page = BooleanField(
default=False,
verbose_name=_("is static page"),
help_text=_(
"is this a post for a page with static URL (e.g. `/help/delivery`)?"
),
)
def __str__(self):
return f"{self.title} | {self.author.first_name} {self.author.last_name}"
class Meta:
verbose_name = _("post")
verbose_name_plural = _("posts")
def save(self, *args, **kwargs):
if self.file:
raise ValueError(
_("markdown files are not supported yet - use markdown content instead")
)
if not any([self.file, self.content]) or all([self.file, self.content]):
raise ValueError(
_(
"a markdown file or markdown content must be provided - mutually exclusive"
)
)
super().save(*args, **kwargs)
class PostTag(NiceModel):
"""
Represents a tag associated with a post.
The PostTag class is used to define and manage tags that can be assigned
to posts. These tags include an internal identifier and a user-friendly
display name. The class supports internationalization for both the internal
identifier and the display name.
Attributes:
is_publicly_visible (bool): Determines if the tag is visible publicly.
tag_name (CharField): An internal tag identifier for the post's tag. It is a required
field with a maximum length of 255 characters.
name (CharField): A user-friendly, unique display name for the post's tag
with a maximum length of 255 characters.
Meta:
verbose_name (str): Human-readable singular name of the PostTag model.
verbose_name_plural (str): Human-readable plural name of the PostTag model.
"""
is_publicly_visible = True
posts: "Post"
tag_name = CharField(
blank=False,
null=False,
max_length=255,
help_text=_("internal tag identifier for the post tag"),
verbose_name=_("tag name"),
)
name = CharField(
max_length=255,
help_text=_("user-friendly name for the post tag"),
verbose_name=_("tag display name"),
unique=True,
)
def __str__(self):
return self.tag_name
class Meta:
verbose_name = _("post tag")
verbose_name_plural = _("post tags")