from django.contrib import admin from django.utils.html import format_html from .models import TbHypn0Item, TbVote, TbBlogPost @admin.register(TbHypn0Item) class TbHypn0ItemAdmin(admin.ModelAdmin): """ Панель управления гипно-картинами (модерация, просмотр статистики, редактирование). Создание новых картин через админку заблокировано (создание только на фронтенде). """ list_display = ( "id", "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_filter = ("i_level", "is_public", "d_created_at") search_fields = ("s_hash_id", "s_title", "s_promo_title", "s_promo_url") readonly_fields = ( "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 = ( ( "Основная информация", { "fields": ( "id", "s_hash_id", "s_title", "file_svg", "svg_preview", "i_file_size", "is_public", ) }, ), ( "Модерация и Smart Retention", { "fields": ( "i_level", "f_score", ), "description": "Уровень модерации и рейтинг 'гравитации' для ротации и очистки хранилища.", }, ), ( "Метрики популярности", { "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): # Создание картин возможно только с фронтенда (требуется обработка растра и согласие пользователя) return False @admin.display(description="Название (HTML)") def title_preview(self, obj): return format_html(obj.s_title) @admin.display(description="Превью SVG") def svg_preview(self, obj): if obj.file_svg: return format_html( '
' '' '
', obj.file_svg.url, ) return "Нет файла" @admin.register(TbVote) class TbVoteAdmin(admin.ModelAdmin): """ Просмотр анонимного журнала голосов и отпечатков (только для чтения). """ list_display = ("id", "k_item", "i_direction", "fingerprint_short", "d_created_at") list_filter = ("i_direction", "d_created_at") search_fields = ("s_fingerprint", "k_item__s_hash_id", "k_item__s_title") readonly_fields = ("id", "k_item", "i_direction", "s_fingerprint", "d_created_at") ordering = ("-d_created_at",) def has_add_permission(self, request): return False def has_change_permission(self, request, obj=None): return False @admin.display(description="Отпечаток (хэш)") def fingerprint_short(self, obj): return f"{obj.s_fingerprint[:12]}..." @admin.register(TbBlogPost) class TbBlogPostAdmin(admin.ModelAdmin): """ Управление статьями блога, документацией и инфо-страницами (HTML + etpgrf). """ list_display = ("id", "s_title_display", "slug", "is_published", "d_published_at", "d_created_at") list_display_links = ("id", "s_title_display") list_filter = ("is_published", "d_published_at", "d_created_at") search_fields = ("s_title", "slug", "s_teaser", "s_content") prepopulated_fields = {"slug": ("s_title",)} readonly_fields = ("id", "d_created_at", "d_updated_at") fieldsets = ( ( "Публикация", { "fields": ( "is_published", "d_published_at", ) }, ), ( "Заголовок и URL", { "fields": ( "s_title", "slug", "f_cover_img", ) }, ), ( "Контент статьи (HTML + etpgrf)", { "fields": ( "s_teaser", "s_content", ), "description": "HTML-текст, типографированный etpgrf. Поддерживается чистая верстка.", }, ), ( "Системные даты", { "fields": ( "id", "d_created_at", "d_updated_at", ), "classes": ("collapse",), }, ), ) @admin.display(description="Заголовок") def s_title_display(self, obj): return format_html(obj.s_title)