"""user virtual background images Свои картинки пользователя для замены фона видео (сессия 35): - таблица `user_backgrounds` — id, владелец (`ON DELETE CASCADE`), путь к файлу относительно `MEDIA_ROOT`, время загрузки. Сами файлы лежат на диске в томе `media` (`backgrounds/{user_id}/{id}.{ext}`), в БД только путь — как у аватаров (`users.avatar_path`). Лимит «не более 10 картинок на пользователя» — политика продукта, проверяется в `services/backgrounds.py`, а не ограничением БД. Настройка отключаемого модуля (`instance_settings.virtual_background`) миграции не требует: `instance_settings` — key-value JSONB, новая настройка это новая строка (см. `services/instance_settings.py`). Revision ID: a37c1b9e0f42 Revises: 4d08a44ad153 Create Date: 2026-08-09 23:30:00.000000 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. revision: str = 'a37c1b9e0f42' down_revision: Union[str, Sequence[str], None] = '4d08a44ad153' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: """Upgrade schema.""" op.create_table( 'user_backgrounds', sa.Column( 'id', postgresql.UUID(as_uuid=True), server_default=sa.text('gen_random_uuid()'), nullable=False, ), sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('path', sa.String(length=512), nullable=False), sa.Column( 'created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False ), sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'), sa.PrimaryKeyConstraint('id'), ) op.create_index( 'ix_user_backgrounds_user_created', 'user_backgrounds', ['user_id', 'created_at'] ) def downgrade() -> None: """Downgrade schema.""" op.drop_index('ix_user_backgrounds_user_created', table_name='user_backgrounds') op.drop_table('user_backgrounds')