SQLModel快速上手

什么是SQLModel

  • 一个用于与SQL数据库交互的库
  • 基于类型注解
  • 与FastAPI兼容性非常高,因为这俩库是一人写的

安装

pip install sqlmodel

完了

创建模型与表

创建模型

假设你需要创建一个名为hero的表,包含以下字段:

  • id
  • name
  • secret_name
  • age

那么你可以这么写:

from sqlmodel import Field, SQLModel, create_engine 
# 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

假设你有好好学基础Python课程,知道一些基础语法,但你仍然可能对上述代码有一些小小的困惑,它可能包含了一些你不清楚的语法,这里稍微做一些解释:

  • name: str:这里的:类型标注的一部分,整体而言,这里就是在告诉Python(以及你的IDE)变量namestr类型的。关于类型标注,你还可以参考Python 类型提示简介 – FastAPI
  • id: int | None:这里除了:还出现了|,这与 C++|差别不大,可以理解为。就是说,变量id可能是int也可能是None

table=True代表了这个类将会被当作表处理。如果不设置这项,那SQLModel不会将此类和数据库中的表对应,之后你也不能创建hero表了

在上述代码中,我们将变量id设为int或是None,因为idhero的自增主键,在创建时不需要人为指定,因此在创建时其值可能是NoneSQLModel在实际往表中添加记录时会帮你处理这个问题。当然,你也需要使用Field()来指定这是个主键

你可能看出来了,这里的namesecret_name必须在创建hero实例时指定,而age不需要

创建数据库中的表

要使用简单方便的sqlite数据库,你可以用以下方式创建数据库引擎:

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

engine = create_engine(sqlite_url, echo=True)

当然,你也可以换成MySQL数据库,那么你需要这么写:

mysql_url = f"mysql+pymysql://{user}:{password}@{host}/{db_name}?charset={charset}"  
# db_name是特定的数据库的名字
# 常见的charset可能形如"utf8mb4"
engine = create_engine(mysql_url, echo=True)

无论使用什么数据库,现在我们都获得了一个连接数据库的引擎engine。由于我们将echo设为了TrueSQLModel会在执行任何SQL语句时都输出对应语句。当然,在生产环境时你不需要他,只需要把他删掉即可,默认值为False

最后,你终于可以创建这个表了:

SQLModel.metadata.create_all(engine)

这句语句执行完毕后,数据库内就会出现hero表了

噢,我猜聪明的你肯定在想,为什么我没有往这个create_all里传任何表类作为参数,但是他还是成功创建了这个表?

事实上,SQLModel会记录你所创建的所有继承于SQLModel类的子类,然后他就能知道创建哪些表

这很重要,因为有时候你会将定义模型创建表放在两个文件里。这时,你就需要在创建表前先import入对应模型,然后再使用create_all函数

往表内插入数据

hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
# 数据来自SQLModel文档,略有删改

session = Session(engine)

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

session.commit()

session.close()
  • hero_1hero_2都是Hero类的实例,很好理解
  • session是与数据库的对话,用于处理这组关于数据库的操作
  • 通过session.add(),你可以往数据库里添加数据
  • session.commit()提交了这些数据,直到此时,数据库内的数据才会真的有所更改
  • 最后,使用session.close()关闭会话

当然,你也可以使用with语句块来自动进行session的关闭:

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

session.commit()后,如果你直接再次访问hero_1,其不会包含数据,因为他需要刷新

这会在你调用了任何hero_1的字段(例如hero_1.id)过后被隐式自动刷新。你也可以使用session.refresh(hero_1)来刷新,使其包含了最新的数据

删改查

在之前的模型基础上:

from sqlmodel import Session, select

with Session(engine) as session:
    statement = select(Hero)
    results = session.exec(statement)
    for hero in results:
        print(hero)

在这里:

  • select()创建了一个statement,这个statement需要放到session.exec()里执行
  • 这里返回的results是一个可迭代对象,而非一个列表。如果你直接需要一个列表,可以使用`session.exec().all()
  • 如果你只需要一个对象,可以使用results.first()

如果你需要某些特定的记录,你可以这么做:

from sqlmodel import Session, select, where

with Session(engine) as session:
    statement = select(Hero).where(Hero.name == "Deadpond")
    results = session.exec(statement)
    for hero in results:
        print(hero)

在这里:

  • where()接受的是一个表达式,而非单纯的传参
  • 如果你单纯只需要通过id查找一个对象,可以使用session.get(Hero, hero_id)

简单的更改对象,然后保存即可

with Session(engine) as session:
    hero = session.get(Hero, hero_id)

    hero.age = 16
    session.add(hero)
    session.commit()

    # 如果你需要在此之后继续访问这个hero对象,你就需要...
    session.refresh(hero)
    # 然后你就可以...
    print(hero)

简单的使用session.delete()即可

with Session(engine) as session:
    hero = session.get(Hero, hero_id)
    session.delete(hero)
    session.commit()
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇