from rest_framework import serializers from .models import AITask, ImageConversation, ModelConfig, ModelProvider class ModelProviderSerializer(serializers.ModelSerializer): class Meta: model = ModelProvider fields = ["id", "name", "display_name", "status", "base_url", "metadata"] read_only_fields = fields class ModelConfigSerializer(serializers.ModelSerializer): provider = ModelProviderSerializer(read_only=True) class Meta: model = ModelConfig fields = ["id", "provider", "name", "display_name", "capability", "endpoint", "unit_price", "status", "metadata"] read_only_fields = fields class ImageConversationSerializer(serializers.ModelSerializer): """图片创作对话:左栏列表用。title 可写(重命名),mode/product 创建时可指定。""" task_count = serializers.SerializerMethodField() class Meta: model = ImageConversation fields = [ "id", "title", "mode", "product", "task_count", "is_deleted", "purged_at", "last_active_at", "created_at", "updated_at", ] read_only_fields = ["id", "task_count", "is_deleted", "purged_at", "last_active_at", "created_at", "updated_at"] def get_task_count(self, obj) -> int: # list 接口已 annotate;无 annotate 时回落实时 count(详情/创建场景) cached = getattr(obj, "_task_count", None) return cached if cached is not None else obj.tasks.count() class ImageConversationTrashSerializer(ImageConversationSerializer): """垃圾桶专用对话契约:只额外暴露一张展示封面,不影响普通对话列表查询。""" cover_preview_url = serializers.SerializerMethodField() class Meta(ImageConversationSerializer.Meta): fields = [*ImageConversationSerializer.Meta.fields, "cover_preview_url"] read_only_fields = [*ImageConversationSerializer.Meta.read_only_fields, "cover_preview_url"] def get_cover_preview_url(self, obj) -> str: return str(getattr(obj, "_trash_cover_preview_url", "") or "") class AITaskSerializer(serializers.ModelSerializer): model_config = ModelConfigSerializer(read_only=True) # 从 request_payload 抽出的分组/标签信息(由 AITaskViewSet annotate 提供;其它调用处无此注解则为 None)。 # 不直接读 obj.request_payload —— 那列已 defer,读了会触发懒加载把几 MB payload 整列拉回。 batch_id = serializers.SerializerMethodField() mode = serializers.SerializerMethodField() def get_batch_id(self, obj): return getattr(obj, "rp_batch_id", None) def get_mode(self, obj): return getattr(obj, "rp_mode", None) class Meta: model = AITask fields = [ "id", "project", "task_type", "batch_id", "mode", "status", "model_config", "provider_task_id", "estimated_cost", "actual_cost", "error_code", "error_message", "submitted_at", "completed_at", "is_deleted", "purged_at", "created_at", "updated_at", ] # batch_id / mode 是显式声明的 SerializerMethodField(本就只读),不能再列进 read_only_fields(DRF 会报错) read_only_fields = [f for f in fields if f not in ("batch_id", "mode")]