1059 字
5 分钟
基础使用

创建表#

定义表#

from sqlmodel import Field, SQLModel, create_engine

class Hero(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str
    secret_name: str
    age: int | None = None
WARNING

这里如果不填 table=True,那么他将只是数据模型,不会被转换为表模型

这里的 age 告诉 Pydantic,age 在验证的时候不是必须的,而且默认值为 None,而 id 被标记为主键,这里把 id 标记为 None 因为主键是必须得,但是他将由数据库生成,而不是由我们的代码生成,因此在创建实例的时候我们不会设置 id,直到我们把他保存到数据库中才会有值.如果我们不设置 default 值,那么在后续使数据验证的时候会带来一些问题.

自动迁移表#

sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"

engine = create_engine(sqlite_url, echo=True)

SQLModel.metadata.create_all(engine)

SQLModel 有一个 metadata 的属性,他是 MetaData 的一个实例,当我们继承 SQLModel 并配置 table=true,他都会在 metadata 中注册.调用 create_all 能创建所有在 metadata 中注册的表

创建会话#

到目前为止,我们只使用引擎来与数据库交互,引擎是我们的所有代码共享的单个对象,负责与数据库通信,处理链接,但是在使用 sqlmodel,将使用他之上的一个工具,也就是会话,我们为每个属于同一组的数据库操作创建一个新的 会话

def create_heroes():
    hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
    hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
    hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)

    session = Session(engine)

    session.add(hero_1)
    session.add(hero_2)
    session.add(hero_3)

    session.commit()

    session.close()

上面的代码记得使用 close 清理资源哦~,但是这样很容易忘记,因此我们需要使用 with 来帮我们管理

def create_heroes():
    hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
    hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
    hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)

    with Session(engine) as session:
        session.add(hero_1)
        session.add(hero_2)
        session.add(hero_3)

        session.commit()

刷新对象#

with Session(engine) as session:
        session.add(hero_1)
        session.add(hero_2)
        session.add(hero_3)

        print("After adding to the session")
        print("Hero 1:", hero_1)
        print("Hero 2:", hero_2)
        print("Hero 3:", hero_3)

        session.commit()

        print("After committing the session")
        print("Hero 1:", hero_1)
        print("Hero 2:", hero_2)
        print("Hero 3:", hero_3)

在这里,我们 commit 后,代码第二次打印的内容居然是空的!这是因为 sqlalchemy 把这些对象标记为过期,没有最新的版本,可以调用 session.refresh(hero_1) 来刷新对象

Select#

def select_heroes():
    with Session(engine) as session:
        statement = select(Hero)
        result = session.exec(statement)
        for hero in results:#一个可迭代对象
	        print(hero)

上面我们得到的 result 只是一个可迭代对象,为了获得完整的列表,我们可以使用.all() 方法

与 Sqlalchemy 的区别#

sqlalchemy 自己的 session 有一个 execute 方法,没有这里的 exec,而 sqlmodel 的 session 直接继承 sqlalchemy 的 session,并添加的额外的 exec,但是添加了一些技巧让他变的更方便,

例如,在 SQLAlchemy 中,您需要在此处添加 .scalars()

heroes = session.execute(select(Hero)).scalars().all()

但是,在选择多个内容时,您必须将其删除(我们稍后会看到)。

SQLModel 的 session.exec() 会为您处理此问题,因此您无需添加 .scalars()

这是 SQLAlchemy 目前无法提供的功能,因为常规的 session.execute() 支持其他几种用例,包括遗留的用例,因此它不能具有所有内部类型注释和技巧来支持此功能。

使用 where#

selece(Hero).where(name=='xyh')

通常使用 name=='xyh' 会返回 true or false,但是 SQLAlchemy 为模型类中的列/字段添加了一些魔力,使这些 Python 比较具有超能力。他会产生一种特殊类型的对象.当使用但是如果你取一个实例

some_hero = Hero(name="Deadpond", secret_name="Dive Wilson")

…并在比较中使用它

some_hero.name == "Deadpond"

…这将产生一个 Python 值

True

def select_heroes():
    with Session(engine) as session:
        statement = select(Hero).where(Hero.age >= 35, Hero.age < 40)
        statement = select(Hero).where(or_(Hero.age <= 35, Hero.age > 90))
        results = session.exec(statement)
        for hero in results:
            print(hero)

读取一行#

第一行或 None#

def select_heroes():
    with Session(engine) as session:
        statement = select(Hero).where(Hero.age < 25)
        results = session.exec(statement)
        hero = results.first()
        print("Hero:", hero)

他会返回一个或 None

恰好等于一行#

def select_heroes():
    with Session(engine) as session:
        statement = select(Hero).where(Hero.name == "Deadpond")
        results = session.exec(statement)
        hero = results.one()
        print("Hero:", hero)

可能存在我们需要确保查询恰好匹配 一行 的情况。

如果有多于一行,则意味着系统存在错误,我们应该终止并报错。

使用 .get() 按 ID 选择#

由于使用 主键 按其 Id 列选择单行是一个常见操作,因此有一个快捷方式

def select_heroes():
    with Session(engine) as session:
        hero = session.get(Hero, 1)
        print("Hero:", hero)

这和 first 一样

基础使用
https://fuwari.vercel.app/posts/编程语言/python小技巧/sqlmodel/基础使用/
作者
FlyingWhite
发布于
2025-01-05
许可协议
CC BY-NC-SA 4.0