80 lines
6.6 KiB
Python
80 lines
6.6 KiB
Python
# Generated by Django 6.1 on 2026-08-22 11:14
|
|
|
|
import django.db.models.deletion
|
|
import django.utils.timezone
|
|
from django.db import migrations, models
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
initial = True
|
|
|
|
dependencies = [
|
|
]
|
|
|
|
operations = [
|
|
migrations.CreateModel(
|
|
name='TbBlogPost',
|
|
fields=[
|
|
('id', models.SmallAutoField(primary_key=True, serialize=False, verbose_name='ID')),
|
|
('s_title', models.CharField(help_text='HTML-заголовок (с HTML-тегами, типографированный etpgrf)', max_length=255, verbose_name='Заголовок')),
|
|
('slug', models.SlugField(max_length=200, unique=True, verbose_name='URL-слаг')),
|
|
('s_teaser', models.TextField(blank=True, help_text='HTML-контент тизера, очищенный и типографированный etpgrf', max_length=1024, verbose_name='Краткое описание / Лид')),
|
|
('s_content', models.TextField(help_text='HTML-контент статьи, очищенный и типографированный etpgrf', verbose_name='Основной HTML-контент')),
|
|
('f_cover_img', models.ImageField(blank=True, null=True, upload_to='blog/covers/%Y/', verbose_name='Обложка')),
|
|
('is_published', models.BooleanField(default=False, verbose_name='Опубликовано')),
|
|
('d_published_at', models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Дата публикации')),
|
|
('d_created_at', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
|
|
('d_updated_at', models.DateTimeField(auto_now=True, verbose_name='Дата обновления')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Статья блога / Страница',
|
|
'verbose_name_plural': 'Статьи блога / Страницы',
|
|
'ordering': ['-d_published_at', '-d_created_at'],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='TbHypn0Item',
|
|
fields=[
|
|
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID')),
|
|
('s_hash_id', models.CharField(max_length=16, unique=True, verbose_name='ID-Хэш')),
|
|
('s_title', models.CharField(help_text='Заголовок для генерации. Включена HTML-типографика. 255 символов максимум.', max_length=255, verbose_name='Название генерации')),
|
|
('file_svg', models.FileField(help_text='Результирующий SVG-файл генерации', upload_to='svg/%Y/%m/', verbose_name='SVG-файл')),
|
|
('i_file_size', models.PositiveIntegerField(default=0, help_text='Размер файла в байтах', verbose_name='Размер файла')),
|
|
('j_metadata', models.JSONField(blank=True, default=dict, help_text='Метаданные и параметры для возможного клонирования настроек', verbose_name='Параметры генерации')),
|
|
('i_likes_count', models.PositiveIntegerField(db_index=True, default=0, verbose_name='Число лайков')),
|
|
('i_views_count', models.PositiveIntegerField(default=0, verbose_name='Число просмотров')),
|
|
('i_claims_count', models.PositiveIntegerField(default=0, verbose_name='Число жалоб')),
|
|
('f_score', models.FloatField(db_index=True, default=0.0, help_text='Рейтинг для Smart Retention и определения, что удалять при чистке по лимитам, а что оставлять', verbose_name='Рейтинг популярности')),
|
|
('i_level', models.IntegerField(choices=[(0, 'Candidate: Шум сознания'), (10, 'Voted: Плеск бессознательного'), (30, 'Moderated: Одобрено Мозговым Слизнем'), (1000, 'Locked: Глубокий транс')], default=0, help_text='Уровень', verbose_name='В какой группе находится SVG-файл генерации')),
|
|
('is_public', models.BooleanField(default=True, help_text='Доступность по прямой ссылке', verbose_name='Публичный доступ')),
|
|
('s_promo_url', models.URLField(blank=True, default='', verbose_name='Промо-ссылка')),
|
|
('s_promo_title', models.CharField(blank=True, default='', max_length=100, verbose_name='Бейдж/автор промо')),
|
|
('i_promo_clicks', models.PositiveIntegerField(default=0, verbose_name='Клики по промо')),
|
|
('d_created_at', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Дата создания')),
|
|
('d_updated_at', models.DateTimeField(auto_now=True, db_index=True, verbose_name='Дата обновления')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Гипно-картина',
|
|
'verbose_name_plural': 'Гипно-картины',
|
|
'ordering': ['-d_created_at'],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='TbVote',
|
|
fields=[
|
|
('id', models.BigAutoField(primary_key=True, serialize=False, verbose_name='ID')),
|
|
('i_direction', models.IntegerField(choices=[(1, 'Like (+1)'), (-2, 'Clime (-2)'), (2, 'Author Like (+2)')], default=1, help_text='Направление голоса', verbose_name='Направление')),
|
|
('s_fingerprint', models.CharField(db_index=True, help_text='SHA256(visitor_uuid + SECRET_KEY) для защиты от накрутки и разделения устройств', max_length=64, verbose_name='Хэш устройства/отпечаток')),
|
|
('d_created_at', models.DateTimeField(auto_now_add=True, verbose_name='Дата голосования')),
|
|
('k_item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='votes', to='hypn0_site.tbhypn0item', verbose_name='Картина')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Голос / Лайк',
|
|
'verbose_name_plural': 'Голоса / Лайки',
|
|
'ordering': ['-d_created_at'],
|
|
'constraints': [models.UniqueConstraint(fields=('k_item', 's_fingerprint'), name='unique_item_fingerprint_vote')],
|
|
},
|
|
),
|
|
]
|