首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用SQLModel & FastAPI将列表和字典等数据类型存储到postgres数据库中?

如何使用SQLModel & FastAPI将列表和字典等数据类型存储到postgres数据库中?
EN

Stack Overflow用户
提问于 2022-03-17 07:28:38
回答 1查看 1.2K关注 0票数 0

我试图使用FastAPI与SQLModel一起写入Postgresql数据库。在这种情况下,我希望将从用于自然语言处理的转换器模型中获得的推理存储到数据库中。

如下面所示,我为推理请求定义了一个SQLModel,它包括一个文本(一个字符串)以及一些要被评分的候选标签(一个字符串列表),根据这些标签可以更多地帧输入的文本。然后在推理对象中定义数据库表,推理结果对应于字符串字典和浮点键值元素,有一个外键与用户实体绑定。

代码语言:javascript
复制
from datetime import datetime
from sqlmodel import Field, SQLModel, Relationship
from typing import Optional

class InferenceBase(SQLModel):
    text: str = Field(nullable=False, index=True)
    candidate_labels: list[str] = Field(nullable=False, index=True)

class Inference(InferenceBase, table=True):
    id: Optional[int] = Field(default=None, nullable=False, primary_key=True)
    result: dict[str, float]
    created_at: Optional[datetime]
    updated_at: Optional[datetime]
    created_by_id: Optional[int] = Field(default=None, foreign_key="user.id")
    created_by: "User" = Relationship(
        sa_relationship_kwargs={
            "lazy": "selectin",
            "primaryjoin": "Inference.created_by_id == User.id",
        }
    )

下一个文件定义了一些模式,用于在需要时从API传递或表示数据。

代码语言:javascript
复制
from app.models.inference import InferenceBase
from app.models.user import UserBase
from pydantic import BaseModel
from typing import Optional

class IInferenceCreate(InferenceBase):
    result: dict[str, float]


class IInferenceRead(InferenceBase):
    id: int
    result: dict[str, float]


class IInferenceUpdate(BaseModel):
    text: Optional[str] = None
    candidate_labels: Optional[list[str]] = None


class IInferenceReadWithUsers(IInferenceRead):
    user: UserBase

下一个文件定义一个CRUD,用于管理表的写入和读取。

代码语言:javascript
复制
from app.crud.base_sqlmodel import CRUDBase
from sqlmodel.ext.asyncio.session import AsyncSession

from app.schemas.inference import IInferenceCreate, IInferenceUpdate
from app.models.inference import Inference
from datetime import datetime


class CRUDInference(CRUDBase[Inference, IInferenceCreate, IInferenceUpdate]):
    async def create_inference(
        self, db_session: AsyncSession, *, obj_in: IInferenceCreate, user_id: int
    ) -> Inference:
        db_obj = Inference.from_orm(obj_in)
        db_obj.created_at = datetime.utcnow()
        db_obj.updated_at = datetime.utcnow()
        db_obj.created_by_id = user_id
        db_session.add(db_obj)
        await db_session.commit()
        await db_session.refresh(db_obj)
        return db_obj


inference = CRUDInference(Inference)

该文件负责管理推理对象的端点,当请求预测并将文本和尾日期标签输入API时,应该将推理结果与所请求的数据和其他一些数据一起写入,为此,我首先将数据合并到检索推理结果的函数中,然后生成一个用于写入数据库的SQLModel值,并返回写入数据库的数据。

代码语言:javascript
复制
from app.schemas.common import (
    IPostResponseBase,
)
from app.utils.nlp import analyze_text
from app.schemas.inference import (
    IInferenceCreate,
    IInferenceRead,
)
from sqlmodel.ext.asyncio.session import AsyncSession
from fastapi import APIRouter, Depends
from app.api import deps
from app import crud
from app.models import Inference
from app.models import InferenceBase
from app.models.user import User

router = APIRouter()


@router.post("/predict/", response_model=IPostResponseBase[IInferenceRead])
async def predict(
    request: InferenceBase,
    db_session: AsyncSession = Depends(deps.get_db),
    current_user: User = Depends(deps.get_current_active_user),
):
    text = request.text
    labels = request.candidate_labels

    result = await analyze_text(text, labels)
    text = result[0]
    candidate_labels = result[1]
    res = result[2]

    inference = IInferenceCreate(
        text=text, candidate_labels=candidate_labels, result=res
    )

    my_inference_on_db = await crud.inference.create_inference(
        db_session, obj_in=inference, user_id=current_user.id
    )

    return IPostResponseBase(data=my_inference_on_db)

问题是,我意识到数据库不是写的,我得到了一个服务器错误。这是我得到的错误日志的一部分:

代码语言:javascript
复制
zero_shot_classification_fastapi_server  | text='Last week I upgraded my iOS version and ever since then my phone has been overheating whenever I use your app.' candidate_labels=['mobile', 'website', 'billing', 'account access'] result={'mobile': 0.946 'billing': 0.011, 'account access': 0.022, 'website': 0.021}
zero_shot_classification_fastapi_server  | <class 'app.schemas.inference.IInferenceCreate'>
zero_shot_classification_fastapi_server  | 2022-03-15 07:13:10,157 INFO sqlalchemy.engine.Engine INSERT INTO inference (text, candidate_labels, result, created_at, updated_at, created_by_id) VALUES (%s, %s, %s, %s, %s, %s) RETURNING inference.id
zero_shot_classification_fastapi_server  | 2022-03-15 07:13:10,157 INFO sqlalchemy.engine.Engine [cached since 1287s ago] ('Last week I upgraded my iOS version and ever since then my phone has been overheating whenever I use your app.', ['mobile', 'website', 'billing', 'account access'], {'mobile': 0.946, 'billing': 0.011, 'account access': 0.022, 'website': 0.021}, datetime.datetime(2022, 3, 15, 7, 13, 10, 156895), datetime.datetime(2022, 3, 15, 7, 13, 10, 156909), 2)
zero_shot_classification_fastapi_server  | 2022-03-15 07:13:10,158 INFO sqlalchemy.engine.Engine ROLLBACK
zero_shot_classification_fastapi_server  | INFO:     172.20.0.1:56274 - "POST /api/v1/predict/ HTTP/1.1" 500 Internal Server Error
zero_shot_classification_fastapi_server  | ERROR:    Exception in ASGI application
zero_shot_classification_fastapi_server  | Traceback (most recent call last):
zero_shot_classification_fastapi_server  |   File "asyncpg/protocol/prepared_stmt.pyx", line 168, in asyncpg.protocol.protocol.PreparedStatementState._encode_bind_msg
zero_shot_classification_fastapi_server  |   File "asyncpg/protocol/codecs/base.pyx", line 206, in asyncpg.protocol.protocol.Codec.encode
zero_shot_classification_fastapi_server  |   File "asyncpg/protocol/codecs/base.pyx", line 111, in asyncpg.protocol.protocol.Codec.encode_scalar
zero_shot_classification_fastapi_server  |   File "asyncpg/pgproto/./codecs/text.pyx", line 29, in asyncpg.pgproto.pgproto.text_encode
zero_shot_classification_fastapi_server  |   File "asyncpg/pgproto/./codecs/text.pyx", line 12, in asyncpg.pgproto.pgproto.as_pg_string_and_size
zero_shot_classification_fastapi_server  | TypeError: expected str, got list
zero_shot_classification_fastapi_server  | 
zero_shot_classification_fastapi_server  | The above exception was the direct cause of the following exception:
zero_shot_classification_fastapi_server  | 
zero_shot_classification_fastapi_server  | Traceback (most recent call last):
zero_shot_classification_fastapi_server  |   File "/usr/local/lib/python3.9/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 442, in _prepare_and_execute
zero_shot_classification_fastapi_server  |     self._rows = await prepared_stmt.fetch(*parameters)
zero_shot_classification_fastapi_server  |   File "/usr/local/lib/python3.9/site-packages/asyncpg/prepared_stmt.py", line 176, in fetch
zero_shot_classification_fastapi_server  |     data = await self.__bind_execute(args, 0, timeout)
zero_shot_classification_fastapi_server  |   File "/usr/local/lib/python3.9/site-packages/asyncpg/prepared_stmt.py", line 241, in __bind_execute
zero_shot_classification_fastapi_server  |     data, status, _ = await self.__do_execute(
zero_shot_classification_fastapi_server  |   File "/usr/local/lib/python3.9/site-packages/asyncpg/prepared_stmt.py", line 230, in __do_execute
zero_shot_classification_fastapi_server  |     return await executor(protocol)
zero_shot_classification_fastapi_server  |   File "asyncpg/protocol/protocol.pyx", line 183, in bind_execute
zero_shot_classification_fastapi_server  |   File "asyncpg/protocol/prepared_stmt.pyx", line 197, in asyncpg.protocol.protocol.PreparedStatementState._encode_bind_msg
zero_shot_classification_fastapi_server  | asyncpg.exceptions.DataError: invalid input for query argument $2: ['mobile', 'website', 'billing', 'accoun... (expected str, got list)
zero_shot_classification_fastapi_server  | 
zero_shot_classification_fastapi_server  | The above exception was the direct cause of the following exception:
zero_shot_classification_fastapi_server  |   File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 129, in greenlet_spawn
zero_shot_classification_fastapi_server  |     value = await result
zero_shot_classification_fastapi_server  |   File "/usr/local/lib/python3.9/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 454, in _prepare_and_execute
zero_shot_classification_fastapi_server  |     self._handle_exception(error)
zero_shot_classification_fastapi_server  |   File "/usr/local/lib/python3.9/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 389, in _handle_exception
zero_shot_classification_fastapi_server  |     self._adapt_connection._handle_exception(error)
zero_shot_classification_fastapi_server  |   File "/usr/local/lib/python3.9/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 682, in _handle_exception
zero_shot_classification_fastapi_server  |     raise translated_error from error
zero_shot_classification_fastapi_server  | sqlalchemy.exc.DBAPIError: (sqlalchemy.dialects.postgresql.asyncpg.Error) <class 'asyncpg.exceptions.DataError'>: invalid input for query argument $2: ['mobile', 'website', 'billing', 'accoun... (expected str, got list)
zero_shot_classification_fastapi_server  | [SQL: INSERT INTO inference (text, candidate_labels, result, created_at, updated_at, created_by_id) VALUES (%s, %s, %s, %s, %s, %s) RETURNING inference.id]
zero_shot_classification_fastapi_server  | [parameters: ('Last week I upgraded my iOS version and ever since then my phone has been overheating whenever I use your app.', ['mobile', 'website', 'billing', 'account access'], {'mobile': 0.946, 'billing': 0.011, 'account access': 0.022, 'website': 0.021}, datetime.datetime(2022, 3, 15, 7, 13, 10, 156895), datetime.datetime(2022, 3, 15, 7, 13, 10, 156909), 2)]
zero_shot_classification_fastapi_server  | (Background on this error at: https://sqlalche.me/e/14/dbapi)

从错误日志中我了解到,问题是数据库不能存储数据类型如列表或字典,如何能够将这些数据类型存储到基于SQLModel的postgres数据库中?

EN

回答 1

Stack Overflow用户

发布于 2022-03-17 09:52:30

尝试使用JSON方言作为字段类型

代码语言:javascript
复制
from sqlalchemy.dialects.postgresql import JSON
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71508461

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档