惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Know Your Adversary
Know Your Adversary
云风的 BLOG
云风的 BLOG
Recent Announcements
Recent Announcements
F
Fortinet All Blogs
B
Blog
罗磊的独立博客
宝玉的分享
宝玉的分享
Vercel News
Vercel News
Martin Fowler
Martin Fowler
N
Netflix TechBlog - Medium
P
Proofpoint News Feed
T
Threatpost
Security Latest
Security Latest
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Stack Overflow Blog
Stack Overflow Blog
I
Intezer
P
Privacy International News Feed
D
Docker
月光博客
月光博客
博客园 - 三生石上(FineUI控件)
M
MIT News - Artificial intelligence
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
L
Lohrmann on Cybersecurity
Google DeepMind News
Google DeepMind News
The Last Watchdog
The Last Watchdog
A
Arctic Wolf
IT之家
IT之家
S
SegmentFault 最新的问题
S
Securelist
博客园 - 叶小钗
N
News and Events Feed by Topic
F
Full Disclosure
Security Archives - TechRepublic
Security Archives - TechRepublic
Engineering at Meta
Engineering at Meta
Hacker News: Ask HN
Hacker News: Ask HN
博客园 - Franky
GbyAI
GbyAI
AI
AI
Y
Y Combinator Blog
WordPress大学
WordPress大学
Latest news
Latest news
Microsoft Security Blog
Microsoft Security Blog
人人都是产品经理
人人都是产品经理
N
News | PayPal Newsroom
The Cloudflare Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
I
InfoQ

冰屋

在TeamSpeak内搭建网易云音乐bot – 冰屋 Linux to go — Rime输入法 – 冰屋 Linux to go — 配置和初体验 – 冰屋 【杂谈】如何快速备考托福 – 冰屋 使用自建N2N加速P2P联机游戏 – 冰屋 FastAPI与SQLModel – 冰屋 FastAPI快速上手 – 冰屋 看不了番剧?自动化你的番剧订阅流程吧! – 冰屋 你好,世界 – 冰屋
SQLModel快速上手 – 冰屋
2024-11-29 · via 冰屋
  • 一个用于与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()