from django.conf import settings from rest_framework import serializers from .models import Asset, AssetFile from .storage import TosStorage _tos_storage = None def _tos(): global _tos_storage if _tos_storage is None: _tos_storage = TosStorage() return _tos_storage class AssetFileSerializer(serializers.ModelSerializer): preview_url = serializers.SerializerMethodField() class Meta: model = AssetFile fields = [ "id", "object_key", "bucket", "content_type", "size_bytes", "width", "height", "duration_ms", "preview_url", "is_primary", ] read_only_fields = [ "id", "object_key", "bucket", "content_type", "size_bytes", "width", "height", "duration_ms", "is_primary", ] def get_preview_url(self, obj): # 存储字段优先(如外部已写入绝对 URL);否则用 object_key 实时签发 TOS 预签名 GET URL if obj.preview_url: return obj.preview_url if not obj.object_key or not settings.TOS.get("endpoint"): return "" try: return _tos().presigned_get_url(object_key=obj.object_key) except Exception: return "" class AssetSerializer(serializers.ModelSerializer): files = AssetFileSerializer(many=True, read_only=True) # 资产归属商品(只读):商品详情页据此只展示「该商品」的 AI 素材,而非全团队 product = serializers.SerializerMethodField() def get_product(self, obj): """解析资产所属商品: 1) 独立生图(图片创作/模特图/平台套图):生图时已写入 metadata.product_id; 2) 项目内生成(基础资产/分镜图等):回溯 origin_task → project → product。 两条路都拿不到则归属 None(如纯手动上传到素材库、与任何商品无关的图)。""" pid = (obj.metadata or {}).get("product_id") if pid: return str(pid) task = obj.origin_task if task and task.project_id and task.project.product_id: return str(task.project.product_id) return None class Meta: model = Asset fields = [ "id", "name", "asset_type", "source", "category", "description", "metadata", "is_deleted", "origin_task", "product", "files", "review_status", "review_error", "created_at", "updated_at", ] read_only_fields = ["id", "review_status", "review_error", "created_at", "updated_at"] class AssetUploadSerializer(serializers.Serializer): file = serializers.FileField() name = serializers.CharField(max_length=255, required=False, allow_blank=True) asset_type = serializers.ChoiceField(choices=Asset.Type.choices) category = serializers.ChoiceField(choices=Asset.Category.choices, default=Asset.Category.UPLOAD) description = serializers.CharField(required=False, allow_blank=True)