From da810a858389304fbc28a9bbcfbc20aa850ee515 Mon Sep 17 00:00:00 2001 From: erjemin Date: Wed, 2 Sep 2026 23:53:35 +0300 Subject: [PATCH] =?UTF-8?q?del:=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8=20?= =?UTF-8?q?=D0=B8=20=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=BA=D0=B0=20(18)=20?= =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=B8=D0=B7=D0=B1?= =?UTF-8?q?=D1=8B=D1=82=D0=BE=D1=87=D0=BD=D0=BE=D0=B5=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D0=B5=20`i=5Ffile=5Fsize`=20=D0=B8=D0=B7=20=D0=BC=D0=BE=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B8=20`TbHypn0Item`=20...=20=D0=B2=D0=B5=D0=B7?= =?UTF-8?q?=D0=B4=D0=B5,=20=D0=B3=D0=B4=D0=B5=20=D0=B8=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BB=D0=BE=D1=81=D1=8C,?= =?UTF-8?q?=20=D0=BF=D0=BE=D1=87=D0=B8=D1=81=D1=82=D0=B8=D0=BB=D0=B8=20+?= =?UTF-8?q?=20=D0=BC=D0=B8=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hypn0/hypn0_site/admin.py | 20 ++++++-- ...ile_size_alter_tbblogpost_slug_and_more.py | 47 +++++++++++++++++++ hypn0/hypn0_site/models.py | 6 --- hypn0/hypn0_site/tests.py | 3 -- hypn0/hypn0_site/views.py | 1 - 5 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 hypn0/hypn0_site/migrations/0003_remove_tbhypn0item_i_file_size_alter_tbblogpost_slug_and_more.py diff --git a/hypn0/hypn0_site/admin.py b/hypn0/hypn0_site/admin.py index 9f35f3a..06909df 100644 --- a/hypn0/hypn0_site/admin.py +++ b/hypn0/hypn0_site/admin.py @@ -191,18 +191,18 @@ class TbHypn0ItemAdmin(admin.ModelAdmin): """ form = TbHypn0ItemAdminForm list_display = ("id", "s_hash_id", "title_preview", "i_level", "i_likes_count", "i_claims_count", - "i_views_count", "i_file_size", "f_score", "is_public", "d_created_at", ) + "i_views_count", "file_size_display", "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", "d_created_at", "d_updated_at", "svg_preview",) + readonly_fields = ("id", "s_hash_id", "file_size_display", "d_created_at", "d_updated_at", "svg_preview",) fieldsets = ( ("ID & Hash-ID", { "fields": (("id", "s_hash_id",), ), "classes": ("collapse", ), }), ("Основная информация", { - "fields": ("s_title", ("file_svg", "svg_preview", "i_file_size", "is_public", ), ) + "fields": ("s_title", ("file_svg", "svg_preview", "file_size_display", "is_public", ), ) }), ("Модерация и Smart Retention", { "fields": (("i_level", "f_score", ), ), @@ -246,6 +246,20 @@ class TbHypn0ItemAdmin(admin.ModelAdmin): ) return "Нет файла" + @admin.display(description="Размер файла") + def file_size_display(self, obj): + if obj and obj.file_svg: + try: + size_bytes = obj.file_svg.size + if size_bytes >= 1024 * 1024: + return f"{size_bytes / (1024 * 1024):.2f} МБ" + elif size_bytes >= 1024: + return f"{size_bytes / 1024:.1f} КБ" + return f"{size_bytes} Б" + except Exception: + return "—" + return "—" + # ---- # АДМИНКА ЛАЙКОВ/ДИСЛАЙКОВ (все только на просмотр) diff --git a/hypn0/hypn0_site/migrations/0003_remove_tbhypn0item_i_file_size_alter_tbblogpost_slug_and_more.py b/hypn0/hypn0_site/migrations/0003_remove_tbhypn0item_i_file_size_alter_tbblogpost_slug_and_more.py new file mode 100644 index 0000000..ede78fe --- /dev/null +++ b/hypn0/hypn0_site/migrations/0003_remove_tbhypn0item_i_file_size_alter_tbblogpost_slug_and_more.py @@ -0,0 +1,47 @@ +# Generated by Django 6.1 on 2026-09-02 20:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('hypn0_site', '0002_alter_tbvote_options_alter_tbblogpost_id_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='tbhypn0item', + name='i_file_size', + ), + migrations.AlterField( + model_name='tbblogpost', + name='slug', + field=models.SlugField(blank=True, default='', max_length=200, unique=True, verbose_name='URL-слаг'), + ), + migrations.AlterField( + model_name='tbhypn0item', + name='f_score', + field=models.FloatField(db_index=True, default=0.0, help_text='Рейтинг для Smart Retention и определения, что удалять при чистке по лимитам, а что оставлять', verbose_name='Рейтинг'), + ), + migrations.AlterField( + model_name='tbhypn0item', + name='i_claims_count', + field=models.PositiveIntegerField(default=0, help_text='Число жалоб на гипнотическую SVG-картину. Поле используется для отображения в интерфейсе. Для расчета рейтинга популярности намеренно НЕ ИСПОЛЬЗУЕТСЯ. Рейтинг будет рассчитан на основе таблицы Голоса/Лайка с учетом весов лайков и клаймов.', verbose_name='Жалоб'), + ), + migrations.AlterField( + model_name='tbhypn0item', + name='i_level', + field=models.IntegerField(choices=[(0, 'Candidate: Шум сознания'), (10, 'Voted: Плеск бессознательного'), (30, 'Moderated: Одобрено Мозговым Слизнем'), (1000, 'Locked: Глубокий транс'), (-20, 'Шейминг (аномальный наплыв жалоб)'), (-10, 'Подозрение на накрутку (спайк лайков)')], default=0, help_text='В какой группе находится SVG-файл генерации', verbose_name='Уровень'), + ), + migrations.AlterField( + model_name='tbhypn0item', + name='i_likes_count', + field=models.PositiveIntegerField(db_index=True, default=1, help_text='Число лайков гипнотической SVG-картины. Поле используется для отображения в интерфейсе. Для расчета рейтинга популярности намеренно НЕ ИСПОЛЬЗУЕТСЯ. Рейтинг будет рассчитан на основе таблицы Голоса/Лайка с учетом весов лайков и клаймов.', verbose_name='Лайков'), + ), + migrations.AlterField( + model_name='tbhypn0item', + name='i_views_count', + field=models.PositiveIntegerField(default=1, verbose_name='Просмотров'), + ), + ] diff --git a/hypn0/hypn0_site/models.py b/hypn0/hypn0_site/models.py index c4ea5bf..4de68b4 100644 --- a/hypn0/hypn0_site/models.py +++ b/hypn0/hypn0_site/models.py @@ -14,7 +14,6 @@ class TbHypn0Item(models.Model): • s_hash_id: хэш-сумма шеринга для SVG-генерации (Hashids) • s_title: Заголовок (до 255 символов, разрешен HTML) • file_svg: SVG-файл генерации - • i_file_size: размер файла в байтах • j_metadata: метаданные файла JSON (параметры алгоритма генерации) • i_likes_count: количество лайков • i_views_count: количество просмотров @@ -62,11 +61,6 @@ class TbHypn0Item(models.Model): verbose_name="SVG-файл", help_text="Результирующий SVG-файл генерации", ) - i_file_size = models.PositiveIntegerField( - default=0, - verbose_name="Размер файла", - help_text="Размер файла в байтах", - ) # НА ВСЯКИЙ СЛУЧАЙ: Метаданные и снимок параметров для возможного клонирования настроек j_metadata = models.JSONField( diff --git a/hypn0/hypn0_site/tests.py b/hypn0/hypn0_site/tests.py index beb873d..6eb392d 100644 --- a/hypn0/hypn0_site/tests.py +++ b/hypn0/hypn0_site/tests.py @@ -413,7 +413,6 @@ class GalleryDetailAndDownloadTests(BaseMediaTestCase): self.item = TbHypn0Item( s_title="Астральный Транс Сознания #42", file_svg=ContentFile(svg_code.encode("utf-8"), name="test_item.svg"), - i_file_size=len(svg_code), j_metadata={ "shape": "circle", "cols": 35, @@ -486,7 +485,6 @@ class GalleryRandomAndNavigationTests(BaseMediaTestCase): item = TbHypn0Item( s_title=f"Гипно Картина #{i}", file_svg=ContentFile(svg_code.encode("utf-8"), name=f"test_item_{i}.svg"), - i_file_size=len(svg_code), j_metadata={"cols": 30 + i}, is_public=True, ) @@ -564,7 +562,6 @@ class UnconsciousMatrixTests(BaseMediaTestCase): item = TbHypn0Item( s_title=f"Тестовый транс #{i}", file_svg=ContentFile(svg_code.encode("utf-8"), name=f"test_matrix_{i}.svg"), - i_file_size=len(svg_code), j_metadata={"cols": 20 + i}, is_public=True, ) diff --git a/hypn0/hypn0_site/views.py b/hypn0/hypn0_site/views.py index c60cd32..e3fd7b0 100644 --- a/hypn0/hypn0_site/views.py +++ b/hypn0/hypn0_site/views.py @@ -246,7 +246,6 @@ def publish(request: HttpRequest) -> HttpResponse: item = TbHypn0Item( s_title=title, file_svg=svg_file, - i_file_size=len(svg_bytes), j_metadata=metadata, i_level=TbHypn0Item.Level.CANDIDATE, is_public=True,