200 lines
6.4 KiB
Python
200 lines
6.4 KiB
Python
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(
|
|
'<div style="max-width: 250px; max-height: 250px; background: #1e293b; padding: 8px; border-radius: 8px;">'
|
|
'<img src="{}" style="max-width: 100%; max-height: 230px;" />'
|
|
'</div>',
|
|
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)
|