You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PostgreSQL的Tortoise-ORM中正确使用ArrayField并实现FastAPI-admin的CRUD

问题原因

FastAPI-admin对ArrayField的默认输入处理逻辑存在问题:当你在表单中输入单个字符串(比如#abcd)时,它会将字符串视为可迭代的字符序列,自动把每个字符拆分成数组的独立元素,而非将整个字符串作为数组的单个元素存入数据库。而直接用Postico操作时,你是明确传入了数组格式的参数(比如{"#abcd"}),所以数据库能正确识别。

Tortoise-ORM的ArrayField(element_type="text")定义本身是正确的,问题出在FastAPI-admin的前端输入解析和后台处理环节。

解决方法

1. 规范Tortoise-ORM模型定义

模型定义可以保持原写法,也可以用更明确的字段类型声明:

from tortoise.models import Model
from tortoise.fields import ArrayField, TextField

class YourModel(Model):
    # 两种写法都有效,推荐用TextField()更直观
    hashtag = ArrayField(element_type=TextField(), null=True)
    # 原写法:hashtag = ArrayField(element_type="text")

2. 自定义FastAPI-admin表单处理逻辑

通过重写模型管理类的创建/更新前置方法,将前端输入转换成正确的数组格式,这里提供两种常用方案:

方案一:逗号分隔输入(用户友好)

让用户输入逗号分隔的标签,后台自动拆分转成数组:

from fastapi_admin.app import app
from fastapi_admin.widgets import TextInput

@app.register(YourModel)
class YourModelAdmin:
    fields = [YourModel.hashtag]
    form_fields = {
        "hashtag": TextInput(
            label="话题标签",
            placeholder="输入逗号分隔的标签,比如#abcd,#wxyz"
        )
    }

    # 创建前处理输入
    async def before_create(self, obj: dict, request):
        if obj.get("hashtag"):
            # 按逗号拆分并去除每个标签的前后空格
            obj["hashtag"] = [tag.strip() for tag in obj["hashtag"].split(",")]
        return obj

    # 更新前处理输入
    async def before_update(self, obj: dict, request):
        if obj.get("hashtag"):
            obj["hashtag"] = [tag.strip() for tag in obj["hashtag"].split(",")]
        return obj

方案二:JSON格式输入(精准可控)

让用户输入标准JSON数组格式,后台解析成数组:

from fastapi_admin.app import app
from fastapi_admin.widgets import TextArea
import json

@app.register(YourModel)
class YourModelAdmin:
    fields = [YourModel.hashtag]
    form_fields = {
        "hashtag": TextArea(
            label="话题标签",
            placeholder='输入JSON格式数组,比如["#abcd", "#wxyz"]'
        )
    }

    async def before_create(self, obj: dict, request):
        if obj.get("hashtag"):
            try:
                obj["hashtag"] = json.loads(obj["hashtag"])
            except json.JSONDecodeError:
                # 解析失败时,将输入内容作为单个元素存入数组
                obj["hashtag"] = [obj["hashtag"].strip()]
        return obj

    async def before_update(self, obj: dict, request):
        if obj.get("hashtag"):
            try:
                obj["hashtag"] = json.loads(obj["hashtag"])
            except json.JSONDecodeError:
                obj["hashtag"] = [obj["hashtag"].strip()]
        return obj

3. 配套FastAPI接口的Pydantic验证

如果是通过FastAPI接口直接提交数据,需要在Pydantic模型中明确声明数组类型,避免参数解析错误:

from pydantic import BaseModel
from typing import List, Optional

class YourModelCreate(BaseModel):
    hashtag: Optional[List[str]] = None

# 在FastAPI路由中使用该模型
@app.post("/your-model/create")
async def create_model_item(item: YourModelCreate):
    await YourModel.create(**item.dict())
    return {"status": "success"}

内容的提问来源于stack exchange,提问作者Shashank Raj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 19:23:13