Files
life-echo/api/services/memoir_images/serializers.py
Sully 2eb066dbec 把“章节正文 + 图片”从 chapters 单表/JSON 结构,重构为“章节 chapter + 段落 section + 图片 memoir_images 独立表”的新数据模型,同时联动修改接口、PDF 导出、异步任务、迁移脚本、测试,以及修复 Android 端聊天列表显示问题。 (#9)
* refactor: 表结构重构,新增段落section和图片image新表

* fix: fix android app import error

* refactor: 重构文件名

* fix: 优化提示词

* fix: 消息气泡显示位置异常问题

---------

Co-authored-by: yangshilin <2157598560@qq.com>
2026-03-13 11:12:10 +08:00

71 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
MemoirImage 模型与 API 用 dict 的互转(与 schema.normalize_image_asset 字段一致)。
"""
from datetime import datetime
from typing import Any
from database.models import MemoirImage
def _parse_optional_datetime(s: str | None):
if not s:
return None
try:
return datetime.fromisoformat(s.replace("Z", "+00:00"))
except (ValueError, AttributeError):
return None
def memoir_image_to_dict(m: MemoirImage | None) -> dict[str, Any] | None:
"""将 MemoirImage 转为前端/API 使用的单条图片 dict。"""
if not m:
return None
d: dict[str, Any] = {
"placeholder": m.placeholder or "",
"description": m.description or "",
"index": m.order_index,
"status": m.status or "pending",
"prompt": m.prompt,
"url": m.url,
"storage_key": m.storage_key,
"provider": m.provider,
"style": m.style,
"size": m.size,
"error": m.error,
"retryable": m.retryable,
"created_at": m.created_at.isoformat() if m.created_at else None,
"updated_at": m.updated_at.isoformat() if m.updated_at else None,
}
return d
def image_dict_to_row_kwargs(d: dict[str, Any] | None) -> dict[str, Any]:
"""从单条图片 dict 提取可写入 MemoirImage 的字段(不含 id/chapter_id/section_id/order_index"""
if not d or not isinstance(d, dict):
return {}
created = d.get("created_at")
updated = d.get("updated_at")
if isinstance(created, str):
created = _parse_optional_datetime(created)
elif not isinstance(created, datetime):
created = None
if isinstance(updated, str):
updated = _parse_optional_datetime(updated)
elif not isinstance(updated, datetime):
updated = None
return {
"placeholder": d.get("placeholder") or None,
"description": d.get("description") or None,
"status": (d.get("status") or "pending").strip() or "pending",
"prompt": d.get("prompt") or None,
"url": d.get("url") or None,
"storage_key": d.get("storage_key") or None,
"provider": d.get("provider") or None,
"style": d.get("style") or None,
"size": d.get("size") or None,
"error": d.get("error") or None,
"retryable": d.get("retryable") if d.get("retryable") is not None else None,
"created_at": created,
"updated_at": updated,
}