SQLAlchemy 模型与 Pydantic 模型

use*_*105 27 python sql sqlalchemy pydantic

我正在按照本教程进行调整,以适应我的需求,在本例中,执行一个 sql 模块,我需要在其中记录 webhook 从 gitlab 问题收集的数据。

对于数据库模块,我使用SQLAlchemy库和PostgreSQL作为数据库引擎。

所以,我想解决一些关于Pydantic库的使用的疑问,特别是这个例子

据我所知,Pydantic 是一个使用带有属性的类进行数据验证的库。

但我不太明白一些事情......Pydantic 的集成是绝对必要的吗?我理解使用 Pydantic 的目的,但我不明白使用 Pydantic 与 SQLAlchemy 模型的集成。

教程中,models.py有以下内容:

from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship

from .database import Base


class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True)
    email = Column(String, unique=True, index=True)
    hashed_password = Column(String)
    is_active = Column(Boolean, default=True)

    items = relationship("Item", back_populates="owner")


class Item(Base):
    __tablename__ = "items"

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, index=True)
    description = Column(String, index=True)
    owner_id = Column(Integer, ForeignKey("users.id"))

    owner = relationship("User", back_populates="items")
Run Code Online (Sandbox Code Playgroud)

schemas.py有以下内容:

from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship

from .database import Base


class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True)
    email = Column(String, unique=True, index=True)
    hashed_password = Column(String)
    is_active = Column(Boolean, default=True)

    items = relationship("Item", back_populates="owner")


class Item(Base):
    __tablename__ = "items"

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, index=True)
    description = Column(String, index=True)
    owner_id = Column(Integer, ForeignKey("users.id"))

    owner = relationship("User", back_populates="items")
Run Code Online (Sandbox Code Playgroud)

我知道在 Pydantic 中定义对象的主要方法是通过模型,而且我也知道模型只是继承自BaseModel的类。

为什么它会创建ItemBase、ItemCreate和继承自ItemBase的Item

ItemBase中,它传递了 Item 表中严格必需的字段?并定义它的类型?

我已经看到 ItemCreate 类稍后用于crud.py创建用户,在我的情况下,我必须对事件执行相同的操作?我的意思是,我必须创建一个这样的类:

class IssueCreate(BaseModel):
    pass
Run Code Online (Sandbox Code Playgroud)

我的例子尝试遵循相同的工作流程:

models.py

from typing import Optional

from pydantic import BaseModel


class ItemBase(BaseModel):
    title: str
    description: Optional[str] = None


class ItemCreate(ItemBase):
    pass


class Item(ItemBase):
    id: int
    owner_id: int

    class Config:
        orm_mode = True


class UserBase(BaseModel):
    email: str


class UserCreate(UserBase):
    password: str


class User(UserBase):
    id: int
    is_active: bool
    items: list[Item] = []

    class Config:
        orm_mode = True

Run Code Online (Sandbox Code Playgroud)

schemas.py

class IssueCreate(BaseModel):
    pass
Run Code Online (Sandbox Code Playgroud)

但我不知道我这样做是否正确,欢迎任何建议。

Her*_*cón 39

你提到的教程是关于FastAPI的。Pydantic 本身与 SQL、SQLAlchemy 或关系数据库无关。FastAPI 向您展示了一种使用关系数据库的方法。


[当使用 FastAPI 时] pydantic 的集成是绝对必要的吗?

是的。根据文档, Pydantic 是一项要求:

要求

Python 3.6+

FastAPI 站在巨人的肩膀上:


为什么它会创建ItemBase、ItemCreate和继承自ItemBase的Item?

Pydantic 模型是 FastAPI 用于定义接收(请求)和返回(响应)数据模式的方式。ItemCreate表示创建项目所需的数据。Item表示查询item时返回的数据。共同的字段ItemCreateItem放置的字段是ItemBase为了避免重复。


在 ItemBase 中,它传递了 Item 表中严格必需的字段?并定义它的类型?

ItemBaseItemCreate具有和共有的字段Item。和桌子没有关系。这只是避免重复的一种方法。pydantic 模型的每个字段都必须有一个类型,这没有什么不寻常的。


就我而言,我必须对这些事件做同样的事情吗?

如果您有类似的场景,其中您接收的数据(请求)和返回的数据(响应)的架构具有公共字段(相同的名称和类型),您可以使用这些字段定义一个模型,并让其他模型继承从中避免重复。


这可能是理解 FastAPI 和 pydantic 的一种(可能是简单的)方式:

FastAPI 将请求转换为 pydantic 模型。这些 pydantic 模型是您的输入数据,也称为模式(可能是为了避免与模型一词的其他用法混淆)。您可以对这些模式执行任何您想要的操作,包括使用它们创建关系数据库模型并保留它们。

无论您想要作为响应返回什么数据,都需要由 FastAPI 转换为 pydantic 模型(模式)。碰巧 pydantic 支持orm_mode选项,允许它解析具有属性而不是字典的任意对象。使用该选项,您可以返回关系数据库模型,FastAPI 会将其转换为相应的模式(使用 pydantic)。

FastAPI 使用 pydantic 的解析和验证功能,但您必须遵循一个简单的规则:您接收的数据必须符合输入模式,并且您想要返回的数据必须符合输出模式。您负责决定两者之间发生的任何事情。