【问题标题】:Trouble getting SQLAlchemy-ImageAttach to work with Pydantic: Any Examples?让 SQLAlchemy-ImageAttach 无法与 Pydantic 一起工作:有什么例子吗?
【发布时间】:2020-08-02 19:33:39
【问题描述】:

我正在尝试将SQLAlchemy-ImageAttachPydanticFastAPI 一起使用,但没有多大成功。

我以前从未使用过 SQLAlchemy-ImageAttach,我确定我用错了。我似乎无法保存任何图像,但我可以让所有非图像方面工作。 (我已经成功集成了SQLAlchemy + Pydantic + FastAPI,有also great examples帮忙。)


我正在尝试创建一个由数据库支持的网站,用户可以在其中创建测验问题并将图像与问题一起嵌入。下面的代码突出显示了与测验问题+图像相关的部分。

我的 Pydantic 模型/模式:

from typing import List, Optional

from pydantic import BaseModel


class QuestionPictureBase(BaseModel):
    pass


class QuestionPicture(QuestionPictureBase):
    id: int
    question_id: int

    class Config:
        orm_mode = True


class QuestionBase(BaseModel):
    header: str
    details: str


class QuestionCreate(QuestionBase):
    pass


class Question(QuestionBase):
    id: int
    creator_id: int
    pictures: List[QuestionPicture] = []

    class Config:
        orm_mode = True


SQLAlchemy 模型:


from sqlalchemy import create_engine, Boolean, Column, ForeignKey, Integer, String, Text
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy_imageattach.entity import Image, image_attachment

SQLALCHEMY_DATABASE_URL = "sqlite:///sqlalch.db"

engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()


class Question(Base):
    __tablename__ = "questions"

    id = Column(Integer, primary_key=True, index=True)
    header = Column(String, index=True)
    details = Column(String, index=True)
    creator_id = Column(Integer, ForeignKey("users.id"))
*** pictures = image_attachment("QuestionPicture", uselist=True) ***
    creator = relationship("User", back_populates="questions")


class QuestionPicture(Base, Image):
    """Model for pictures associated with the question."""

    __tablename__ = "question_pictures"

    id = Column(Integer, primary_key=True)
    # Not sure if the question ID should also be a unique identifier
    # question_id = Column(Integer, ForeignKey("questions.id"), primary_key=True)
    question_id = Column(Integer, ForeignKey("questions.id"))
    question = relationship("Question", back_populates="pictures")

突出显示的行

*** pictures = image_attachment("QuestionPicture", uselist=True) ***

是我认为我做错了的地方。但我不太确定我应该做什么。

我只是不明白应该如何使用image_attachment 函数调用。它似乎在 SQLAlchemy-ImageAttach 文档中“自动”工作,我不明白。

有没有人有任何使用 SQLAlchemy-ImageAttach + Pydantic (+ FastAPI) 的工作示例。最让我困惑的是与 Pydantic 的交互。


更新

有人要求提供更多细节,但要提出的问题实在是太多了。因此,我创建了一个 git 分支,其中包含所有后端,但只包含后端,称为 temppushed it to a public GitHub repo


解决方案

@r-m-n 下面的解决方案让我取得了很大进展,但我的主要问题是我不清楚我的pictures 数据库需要包含什么。

在查看了一些错误输出并阅读了源代码后,我找到了the needed structure here,并将我的alembic(数据库版本控制)代码调整如下:

def upgrade():
    op.create_table(
        "question_pictures",
        sa.Column("id", sa.Integer, primary_key=True, index=True),
        sa.Column(
            "question_id", sa.Integer, sa.ForeignKey("questions.id"), nullable=False
        ),
        sa.Column("width", sa.Integer, nullable=False),
        sa.Column("height", sa.Integer, nullable=False),
        #: (:class:`str`) The mimetype of the image
        #: e.g. ``'image/jpeg'``, ``'image/png'``.
        sa.Column("mimetype", sa.String(255), nullable=False),
        sa.Column("original", sa.Boolean, nullable=False, default=False),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
    )

在上面的列表中,缺少的是 widthheightoriginalmimetypecreated_at,我不知道我需要添加它们。

(上面的sasqlalchemy的缩写,opalembic.op的缩写。)

【问题讨论】:

  • 我也从未使用过 SQLAlchemy 图像,但您介意分享获取图像并填充 pydantic 类的部分吗?从本教程sqlalchemy-imageattach.readthedocs.io/en/1.1.0/api/entity.html看来你可以同时使用blob和file,所以错误可能在于你填充模型数据的方式(只是提示可能的原因)
  • 是的,@lsabi,我可以分享整件事,但我认为只回答一个问题就太难了。我已经编辑了原始问题以包含指向我创建并将其推送到的 github 存储库的链接。
  • 我没有运行它,但是会不会是在 pydantic 模型中使用 pass 在在线 github.com/lazarillo/kids-quizzes/blob/temp/backend/src/sqlalch/… 创建字典时会导致一些问题?终端返回什么错误?

标签: python sqlalchemy pydantic


【解决方案1】:

SQLAlchemy-ImageAttach 在创建关系时默认使用lazy=dynamic 参数:https://github.com/dahlia/sqlalchemy-imageattach/blob/master/sqlalchemy_imageattach/entity.py#L148。所以question.pictures返回一个Query对象而不是一个列表,你需要调用question.pictures.all()来获取图片列表。

您可以设置lazy=selectlazy=joined。查看更多关于惰性参数here

pictures = image_attachment("QuestionPicture", uselist=True, lazy='select')

【讨论】:

  • 我已经尝试过并且能够继续前进,但仍然没有让一切正常。我已经授予了赏金,这样我就不必担心忘记并让它过期。 :( 但是一旦我完成了所有工作,我会更新并接受。
  • 我已经用我的问题的最终解决方案更新了我的问题,但是这个答案帮助我接近了,谢谢!
猜你喜欢
  • 2017-01-16
  • 1970-01-01
  • 1970-01-01
  • 2012-01-16
  • 2020-02-29
  • 2011-04-25
  • 2014-11-22
  • 2014-05-15
  • 2010-10-16
相关资源
最近更新 更多