add: админка (17) CodeMirror в админке настроен для SVG-генераций (2)

This commit is contained in:
2026-08-29 17:42:41 +03:00
parent 2e0b10b285
commit f9042b0e59
2 changed files with 49 additions and 92 deletions
+43 -86
View File
@@ -147,10 +147,7 @@ class TbHypn0ItemAdminForm(CodeMirrorFormMixin):
model = TbHypn0Item model = TbHypn0Item
fields = ( fields = (
's_title', "s_promo_title", "s_promo_url", "i_level", 's_title', "s_promo_title", "s_promo_url", "i_level",
"i_file_size", "i_likes_count", "i_views_count", "i_claims_count", "f_score",
"i_likes_count",
"i_views_count",
"i_claims_count",
"i_promo_clicks", "i_promo_clicks",
) )
@@ -173,8 +170,19 @@ class TbHypn0ItemAdminForm(CodeMirrorFormMixin):
self.setup_codemirror_field('s_promo_url', language='text', self.setup_codemirror_field('s_promo_url', language='text',
css_class='codemirror-width-xl codemirror-no-lines') css_class='codemirror-width-xl codemirror-no-lines')
self.setup_codemirror_field('i_likes_count', language='text', self.setup_codemirror_field('i_likes_count', language='text',
css_class='codemirror-width-xl codemirror-no-lines') css_class='codemirror-width-s codemirror-no-lines')
self.setup_codemirror_field('i_claims_count', language='text',
css_class='codemirror-width-s codemirror-no-lines')
self.setup_codemirror_field('i_views_count', language='text',
css_class='codemirror-width-s codemirror-no-lines')
self.setup_codemirror_field('f_score', language='text',
css_class='codemirror-width-s codemirror-no-lines')
self.setup_codemirror_field('i_promo_clicks', language='text',
css_class='codemirror-width-s codemirror-no-lines')
self.setup_codemirror_field('j_metadata', language='json',
css_class='codemirror-width-sl codemirror-min-height-10')
# Конфигурация админки
@admin.register(TbHypn0Item) @admin.register(TbHypn0Item)
class TbHypn0ItemAdmin(admin.ModelAdmin): class TbHypn0ItemAdmin(admin.ModelAdmin):
""" """
@@ -182,92 +190,39 @@ class TbHypn0ItemAdmin(admin.ModelAdmin):
Создание новых картин через админку заблокировано (создание только на фронтенде). Создание новых картин через админку заблокировано (создание только на фронтенде).
""" """
form = TbHypn0ItemAdminForm form = TbHypn0ItemAdminForm
list_display = ( list_display = ("id", "s_hash_id", "title_preview", "i_level", "i_likes_count", "i_claims_count",
"id", "i_views_count", "i_file_size", "f_score", "is_public", "d_created_at", )
"s_hash_id",
"title_preview",
"i_level",
"i_likes_count",
"i_claims_count",
"i_views_count",
"f_score",
"is_public",
"d_created_at",
)
list_display_links = ("id", "s_hash_id", "title_preview") list_display_links = ("id", "s_hash_id", "title_preview")
list_filter = ("i_level", "is_public", "d_created_at") list_filter = ("i_level", "is_public", "d_created_at")
search_fields = ("s_hash_id", "s_title", "s_promo_title", "s_promo_url") search_fields = ("s_hash_id", "s_title", "s_promo_title", "s_promo_url")
readonly_fields = ( readonly_fields = ("id", "s_hash_id", "i_file_size", "d_created_at", "d_updated_at", "svg_preview",)
"id",
"s_hash_id",
"i_file_size",
# "i_likes_count",
"i_views_count",
"i_claims_count",
"i_promo_clicks",
"d_created_at",
"d_updated_at",
"svg_preview",
)
fieldsets = ( fieldsets = (
("ID & Hash-ID", { ("ID & Hash-ID", {
"fields": (("id", "s_hash_id",), ), "fields": (("id", "s_hash_id",), ),
"classes": ("collapse",), "classes": ("collapse", ),
}), }),
("Основная информация", { ("Основная информация", {
"fields": ("s_title", "fields": ("s_title", ("file_svg", "svg_preview", "i_file_size", "is_public", ), )
"file_svg", }),
"svg_preview", ("Модерация и Smart Retention", {
"i_file_size", "fields": (("i_level", "f_score", ), ),
"is_public", "description": "Уровень модерации и рейтинг 'гравитации' для ротации и очистки хранилища.",
) }),
}, ("Метрики популярности", {
), "fields": ("i_likes_count", "i_claims_count", "i_views_count", ),
( "classes": ("collapse", ),
"Модерация и Smart Retention", }),
{ ("Промо-блок (Спонсоры и Авторы)", {
"fields": ( "fields": ("s_promo_url", "s_promo_title", "i_promo_clicks", ),
"i_level", "classes": ("collapse",),
"f_score", }),
), ("Метаданные генерации", {
"description": "Уровень модерации и рейтинг 'гравитации' для ротации и очистки хранилища.", "fields": ("j_metadata",),
}, }),
), ("Штампы времени", {
( "fields": ("d_created_at", "d_updated_at"),
"Метрики популярности", "classes": ("collapse",),
{ }),
"fields": (
"i_likes_count",
"i_claims_count",
"i_views_count",
),
},
),
(
"Промо-блок (Спонсоры и Авторы)",
{
"fields": (
"s_promo_url",
"s_promo_title",
"i_promo_clicks",
),
"classes": ("collapse",),
},
),
(
"Метаданные генерации",
{
"fields": ("j_metadata",),
"classes": ("collapse",),
},
),
(
"Временные метки",
{
"fields": ("d_created_at", "d_updated_at"),
"classes": ("collapse",),
},
),
) )
def has_add_permission(self, request): def has_add_permission(self, request):
@@ -284,15 +239,16 @@ class TbHypn0ItemAdmin(admin.ModelAdmin):
def svg_preview(self, obj): def svg_preview(self, obj):
if obj.file_svg: if obj.file_svg:
return format_html( return format_html(
'<div style="max-width: 250px; max-height: 250px; background: #1e293b; padding: 8px; border-radius: 8px;">' '<div style="max-width: 280px; max-height: 280px; background: #80808080; padding: 8px; border-radius: 8px;">'
'<img src="{}" style="max-width: 100%; max-height: 230px;" />' '<img src="{}" width="100%" />'
'</div>', '</div>',
obj.file_svg.url, obj.file_svg.url,
) )
return "Нет файла" return "Нет файла"
# ---- # ----
# АДМИНКА ЛАЙКОВ/ДИСЛАЙКОВ # АДМИНКА ЛАЙКОВ/ДИСЛАЙКОВ (все только на просмотр)
@admin.register(TbVote) @admin.register(TbVote)
class TbVoteAdmin(admin.ModelAdmin): class TbVoteAdmin(admin.ModelAdmin):
""" """
@@ -402,6 +358,7 @@ class BlogPostAdminForm(CodeMirrorFormMixin):
self.setup_codemirror_field('s_content', language='html', self.setup_codemirror_field('s_content', language='html',
css_class='codemirror-width-xl codemirror-min-height-10') css_class='codemirror-width-xl codemirror-min-height-10')
# Конфигурация админки
@admin.register(TbBlogPost) @admin.register(TbBlogPost)
class TbBlogPostAdmin(RequestInFormMixin, admin.ModelAdmin): class TbBlogPostAdmin(RequestInFormMixin, admin.ModelAdmin):
""" """
+6 -6
View File
@@ -80,18 +80,18 @@ class TbHypn0Item(models.Model):
i_likes_count = models.PositiveIntegerField( i_likes_count = models.PositiveIntegerField(
default=1, default=1,
db_index=True, db_index=True,
verbose_name="Число лайков", verbose_name="Лайков",
help_text="Число лайков гипнотической SVG-картины. Поле используется для отображения в интерфейсе. Для расчета" help_text="Число лайков гипнотической SVG-картины. Поле используется для отображения в интерфейсе. Для расчета"
" рейтинга популярности намеренно НЕ ИСПОЛЬЗУЕТСЯ. Рейтинг будет рассчитан на основе таблицы" " рейтинга популярности намеренно НЕ ИСПОЛЬЗУЕТСЯ. Рейтинг будет рассчитан на основе таблицы"
" <tt>Голоса/Лайка</tt> с учетом весов лайков и клаймов.", " <tt>Голоса/Лайка</tt> с учетом весов лайков и клаймов.",
) )
i_views_count = models.PositiveIntegerField( i_views_count = models.PositiveIntegerField(
default=1, default=1,
verbose_name="Число просмотров", verbose_name="Просмотров",
) )
i_claims_count = models.PositiveIntegerField( i_claims_count = models.PositiveIntegerField(
default=0, default=0,
verbose_name="Число жалоб", verbose_name="Жалоб",
help_text="Число жалоб на гипнотическую SVG-картину. Поле используется для отображения в интерфейсе. Для расчета" help_text="Число жалоб на гипнотическую SVG-картину. Поле используется для отображения в интерфейсе. Для расчета"
" рейтинга популярности намеренно НЕ ИСПОЛЬЗУЕТСЯ. Рейтинг будет рассчитан на основе таблицы" " рейтинга популярности намеренно НЕ ИСПОЛЬЗУЕТСЯ. Рейтинг будет рассчитан на основе таблицы"
" <tt>Голоса/Лайка</tt> с учетом весов лайков и клаймов.", " <tt>Голоса/Лайка</tt> с учетом весов лайков и клаймов.",
@@ -99,7 +99,7 @@ class TbHypn0Item(models.Model):
f_score = models.FloatField( f_score = models.FloatField(
default=0.0, default=0.0,
db_index=True, db_index=True,
verbose_name="Рейтинг популярности", verbose_name="Рейтинг",
help_text="Рейтинг для Smart Retention и определения, что удалять при чистке по лимитам, а что оставлять", help_text="Рейтинг для Smart Retention и определения, что удалять при чистке по лимитам, а что оставлять",
) )
@@ -107,8 +107,8 @@ class TbHypn0Item(models.Model):
i_level = models.IntegerField( i_level = models.IntegerField(
choices=Level.choices, choices=Level.choices,
default=Level.CANDIDATE, default=Level.CANDIDATE,
help_text="Уровень", verbose_name="Уровень",
verbose_name="В какой группе находится SVG-файл генерации", help_text="В какой группе находится SVG-файл генерации",
) )
is_public = models.BooleanField( is_public = models.BooleanField(
default=True, default=True,