feat: Separate asset origin type from content type for improved asset categorization and handling.

This commit is contained in:
xds
2026-02-07 14:41:03 +03:00
parent ce87ac7edb
commit 305ad24576
13 changed files with 53 additions and 17 deletions

View File

@@ -2,18 +2,23 @@ from datetime import datetime, UTC
from enum import Enum
from typing import Optional, Any, List
from pydantic import BaseModel, computed_field, Field
from pydantic import BaseModel, computed_field, Field, model_validator
class AssetType(str, Enum):
class AssetContentType(str, Enum):
IMAGE = 'image'
PROMPT = 'prompt'
class AssetType(str, Enum):
UPLOADED = 'uploaded'
GENERATED = 'generated'
class Asset(BaseModel):
id: Optional[str] = None
name: str
type: AssetType
type: AssetType = AssetType.GENERATED
content_type: AssetContentType = AssetContentType.IMAGE
linked_char_id: Optional[str] = None
data: Optional[bytes] = None
tg_doc_file_id: Optional[str] = None
@@ -26,6 +31,33 @@ class Asset(BaseModel):
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
updated_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
@model_validator(mode='before')
@classmethod
def check_legacy_type(cls, data: Any) -> Any:
if isinstance(data, dict):
# Если поле type содержит старые значения ("image", "prompt"),
# переносим их в content_type, а type ставим по умолчанию (GENERATED)
# или пытаемся угадать.
# Но по задаче мы дефолтим в GENERATED, и script'ом поправим.
raw_type = data.get('type')
if raw_type in ['image', 'prompt']:
data['content_type'] = raw_type
# Если в базе нет нового поля type, оно встанет в default=GENERATED
# Чтобы не вызывало ошибку валидации AssetType, меняем его или удаляем,
# полагаясь на default.
# Но если мы просто удалим, поле type примет дефолтное значение.
# Однако, если мы хотим явно отличить, можно ничего не делать,
# но тогда валидация поля `type` упадет, т.к. "image" != "generated".
# Поэтому удаляем старое значение из type, чтобы сработал дефолт.
if 'type' in data:
del data['type']
# Если content_type нет в данных (легаси), пытаемся его восстановить из удалённого type
# (выше мы его переложили).
return data
# --- CALCULATED FIELD ---
@computed_field
def url(self) -> str: