#
一、声明模型
首先我们定义了模块级结构,这些结构将形成我们将从数据库中查询的结构。这种结构称为?声明性映射 ,讲白了其实就是SQL 表中存在的元数据。
from?sqlalchemy?import?Column
from?sqlalchemy?import?ForeignKey
from?sqlalchemy?import?Integer
from?sqlalchemy?import?String
from?sqlalchemy.orm?import?declarative_base
from?sqlalchemy.orm?import?relationship
Base?=?declarative_base()
class?User(Base):
????__tablename__?=?"user"
????id?=?Column(Integer,?primary_key=True)
????name?=?Column(String(30))
????fullname?=?Column(String)
????addresses?=?relationship(
????????"Address",?back_populates="user",?cascade="all,?delete-orphan"
????)
????def?__repr__(self):
????????return?f"User(id={self.id!r},?name={self.name!r},?fullname={self.fullname!r})"
class?Address(Base):
????__tablename__?=?"address"
????id?=?Column(Integer,?primary_key=True)
????email_address?=?Column(String,?nullable=False)
????user_id?=?Column(Integer,?ForeignKey("user.id"),?nullable=False)
????user?=?relationship("User",?back_populates="addresses")
????def?__repr__(self):
????????return?f"Address(id={self.id!r},?email_address={self.email_address!r})"
信息注释:
Column 表示数据库表中的列。primary_key 设置字段为主键ForeignKey 设置字段为外键nullable 可为空,意思是可为空值relationship 提供两个映射类之间的关系back_populates 是指定和哪个类作映射关系cascade 级联,可理解意思就是主表数据被删除,关联的子表跟随操作
二、建立连接
from?sqlalchemy?import?create_engine
_SQLALCHEMY_DATABASE_URL?=?"mysql+pymysql://root:123456@192.168.0.110:3306/sqlalchemy_db"
engine?=?create_engine(
????#?echo=True参数表示连接发出的?SQL?将被记录到标准输出
????#?future=True是为了方便便我们充分利用sqlalchemy2.0样式用法
????_SQLALCHEMY_DATABASE_URL,?echo=True,?future=True
)
信息注释:
- 这里就是定义一个连接数据库的变量
- 调用
creat_engine 方法来连接指定的数据库
三、创建数据表
Base.metadata.create_all(engine)
信息注释:
- 创建存储在此元数据中的所有表。
- 默认情况下有条件,不会尝试重新创建目标数据库中已经存在的表。
注意点:
- 如果你使用的是sqlite数据库,则直接运行代码就会自动根据定义的模型自动创建数据;如果你是mysql数据库,则需要自己先建好表,不然运行时会抛出数据表不存在的问题。
上述代码运行完成,在控制台就会产生一些日志,没有报错就表示成功了:
2022-05-01?13:35:53,251?INFO?sqlalchemy.engine.Engine?SELECT?DATABASE()
2022-05-01?13:35:53,251?INFO?sqlalchemy.engine.Engine?[raw?sql]?{}
2022-05-01?13:35:53,255?INFO?sqlalchemy.engine.Engine?SELECT?@@sql_mode
2022-05-01?13:35:53,255?INFO?sqlalchemy.engine.Engine?[raw?sql]?{}
2022-05-01?13:35:53,256?INFO?sqlalchemy.engine.Engine?SELECT?@@lower_case_table_names
2022-05-01?13:35:53,257?INFO?sqlalchemy.engine.Engine?[raw?sql]?{}
2022-05-01?13:35:53,260?INFO?sqlalchemy.engine.Engine?BEGIN?(implicit)
2022-05-01?13:35:53,260?INFO?sqlalchemy.engine.Engine?SELECT?COUNT(*)?FROM?information_schema.tables?WHERE?table_schema?=?%(table_schema)s?AND?table_name?=?%(table_name)s
2022-05-01?13:35:53,260?INFO?sqlalchemy.engine.Engine?[generated?in?0.00014s]?{'table_schema':?'sqlalchemy_db',?'table_name':?'user'}
2022-05-01?13:35:53,262?INFO?sqlalchemy.engine.Engine?SELECT?COUNT(*)?FROM?information_schema.tables?WHERE?table_schema?=?%(table_schema)s?AND?table_name?=?%(table_name)s
2022-05-01?13:35:53,263?INFO?sqlalchemy.engine.Engine?[cached?since?0.002399s?ago]?{'table_schema':?'sqlalchemy_db',?'table_name':?'address'}
2022-05-01?13:35:53,265?INFO?sqlalchemy.engine.Engine?COMMIT
Process?finished?with?exit?code?0
#
一、创建对象并持久化
现在准备往数据库中插入数据
- 通过创建
User 和Address 对象的实例来实现这一点,这些对象具有init() 声明性映射过程自动建立的方法。 - 使用一个名为
Session 的对象将它们传递给数据库,该对象利用SessionEngine 与数据库进行交互。 - 使用
Session.add_all() 方法一次添加多个对象,该Session.commit() 方法将用于刷新对数据库的任何未决更改,然后提交当前数据库事务,只要使用 ,该事务始终在进行中Session
from?sqlalchemy.orm?import?Session
with?Session(engine)?as?session:
????spongebob?=?User(
????????name="zhangsansan",
????????fullname="sansan",
????????addresses=[Address(email_address="sansan@sqlalchemy.com")],
????)
????sandy?=?User(
????????name="lixiaoxiao",
????????fullname="xiaoxiao",
????????addresses=[
????????????Address(email_address="xiaoxiao@sqlalchemy.com"),
????????????Address(email_address="dongdong@squirrelpower.com"),
????????],
????)
????patrick?=?User(name="lidongdong",?fullname="dongdong")
????session.add_all([spongebob,?sandy,?patrick])
????session.commit()
信息注释:
- 这里使用的是上下文管理器的方式来插入数据,数据执行完成后,会自动执行关闭连接操作
上述代码执行完成数据插入后,在控制台就会产生一些日志,没有报错就表示成功了:
2022-05-01?14:43:26,282?INFO?sqlalchemy.engine.Engine?INSERT?INTO?user?(name,?fullname)?VALUES?(%(name)s,?%(fullname)s)
2022-05-01?14:43:26,282?INFO?sqlalchemy.engine.Engine?[generated?in?0.00015s]?{'name':?'zhangsansan',?'fullname':?'sansan'}
2022-05-01?14:43:26,285?INFO?sqlalchemy.engine.Engine?INSERT?INTO?user?(name,?fullname)?VALUES?(%(name)s,?%(fullname)s)
2022-05-01?14:43:26,286?INFO?sqlalchemy.engine.Engine?[cached?since?0.003192s?ago]?{'name':?'lixiaoxiao',?'fullname':?'xiaoxiao'}
2022-05-01?14:43:26,289?INFO?sqlalchemy.engine.Engine?INSERT?INTO?user?(name,?fullname)?VALUES?(%(name)s,?%(fullname)s)
2022-05-01?14:43:26,289?INFO?sqlalchemy.engine.Engine?[cached?since?0.006635s?ago]?{'name':?'lidongdong',?'fullname':?'dongdong'}
2022-05-01?14:43:26,293?INFO?sqlalchemy.engine.Engine?INSERT?INTO?address?(email_address,?user_id)?VALUES?(%(email_address)s,?%(user_id)s)
2022-05-01?14:43:26,293?INFO?sqlalchemy.engine.Engine?[generated?in?0.00025s]?{'email_address':?'sansan@sqlalchemy.com',?'user_id':?1}
2022-05-01?14:43:26,300?INFO?sqlalchemy.engine.Engine?INSERT?INTO?address?(email_address,?user_id)?VALUES?(%(email_address)s,?%(user_id)s)
2022-05-01?14:43:26,300?INFO?sqlalchemy.engine.Engine?[cached?since?0.007286s?ago]?{'email_address':?'xiaoxiao@sqlalchemy.com',?'user_id':?2}
2022-05-01?14:43:26,303?INFO?sqlalchemy.engine.Engine?INSERT?INTO?address?(email_address,?user_id)?VALUES?(%(email_address)s,?%(user_id)s)
2022-05-01?14:43:26,303?INFO?sqlalchemy.engine.Engine?[cached?since?0.009968s?ago]?{'email_address':?'dongdong@squirrelpower.com',?'user_id':?2}
2022-05-01?14:43:26,310?INFO?sqlalchemy.engine.Engine?COMMIT
Process?finished?with?exit?code?0
#
一、数据查询-简单的选择
from?sqlalchemy.orm?import?Session
from?sqlalchemy?import?select
session?=?Session(engine)
stmt?=?select(User).where(User.name.in_(["zhangsansan",?"lidongdong"]))
for?user?in?session.scalars(stmt):
????print(f"运行结果:{user}")
信息注释:
运行结果:
2022-05-01?15:05:28,425?INFO?sqlalchemy.engine.Engine?SELECT?user.id,?user.name,?user.fullname?
FROM?user?
WHERE?user.name?IN?(%(name_1_1)s,?%(name_1_2)s)
2022-05-01?15:05:28,425?INFO?sqlalchemy.engine.Engine?[generated?in?0.00068s]?{'name_1_1':?'zhangsansan',?'name_1_2':?'lidongdong'}
运行结果:User(id=1,?name='zhangsansan',?fullname='sansan')
运行结果:User(id=3,?name='lidongdong',?fullname='dongdong')
从查询结果可以清晰看到符合条件的两条数据显示出来了,而且查询的SQL 语句也体现出来了,是不是慢慢的感觉SQL 语句的技能也提升了呢
二、数据查询-多表
from?sqlalchemy.orm?import?Session
from?sqlalchemy?import?select
session?=?Session(engine)
stmt?=?(
????select(Address).join(
????????Address.user
????).where(
????????User.name?==?"zhangsansan"
????).where(
????????Address.user_id?==?1
????)
)
sandy_address?=?session.scalars(stmt).one()
print(f"运行结果:{sandy_address}")
信息注释:
scalars 是将标量筛选应用于结果上,one 是拿一条结果
运行结果:
2022-05-01?15:10:13,712?INFO?sqlalchemy.engine.Engine?SELECT?address.id,?address.email_address,?address.user_id?
FROM?address?INNER?JOIN?user?ON?user.id?=?address.user_id?
WHERE?user.name?=?%(name_1)s?AND?address.user_id?=?%(user_id_1)s
2022-05-01?15:10:13,712?INFO?sqlalchemy.engine.Engine?[generated?in?0.00021s]?{'name_1':?'zhangsansan',?'user_id_1':?1}
运行结果:Address(id=1,?email_address='sansan@sqlalchemy.com')
从查询结果可以清晰看到符合条件的数据显示出来了,体现的SQL 语句中也可以清晰看到,使用的就是JOIN 关联查询。
#
一、数据更新
from?sqlalchemy.orm?import?Session
from?sqlalchemy?import?select
session?=?Session(engine)
stmt?=?select(User).where(User.name?==?"zhangsansan")
patrick?=?session.scalars(stmt).one()
stmt?=?(
????select(Address).join(
????????Address.user
????).where(
????????User.name?==?"lixiaoxiao"
????).where(
????????Address.user_id?==?2
????)
)
sandy_address?=?session.scalars(stmt).one()
#???进行更改-给用户再增加一个关联的邮箱地址
patrick.addresses.append(
????Address(email_address="sansan@163.com")
)
#???进行更改-对用户邮箱进行修改
sandy_address.email_address?=?"xiaoxiao@qq.com"
session.commit()
信息注释:
append 就是追加的意思,查询到指定用户进行数据新增email_address= 是赋值操作,是查询到指定用户,对原有数据进行修改,也就是替换一个新的
#
一、数据删除
from?sqlalchemy.orm?import?Session
from?sqlalchemy?import?select
session?=?Session(engine)
stmt?=?select(User).where(User.name?==?"zhangsansan")
patrick?=?session.scalars(stmt).one()
stmt?=?select(User).where(User.name?==?"zhangsansan")
patrick?=?session.scalars(stmt).one()
stmt?=?(
????select(Address).join(
????????Address.user
????).where(
????????User.name?==?"lixiaoxiao"
????).where(
????????Address.user_id?==?2
????)
)
sandy_address?=?session.scalars(stmt).one()
#?一些删除
sandy?=?session.get(User,?2)
sandy.addresses.remove(sandy_address)
session.flush()
session.delete(patrick)
session.commit()
信息注释:
session.get(User, 2) 是根据映射表获取数据sandy.addresses.remove(sandy_address) 根据查询到的数据进行删除session.flush() 是将所有对象更改刷新到数据库session.delete(patrick) 是根据查询到的进行删除
注意点:
remove 一般来说,是操作对象还存在,只是从一个集合或容器中移除;而delete ,则会执行销毁对象的操作,容器都不在了
今天先聊到这里吧,以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的一键 3 连【 点赞、收藏、分享 】哟,谢谢!
未完成,待续……
一直在努力,希望你也是!
微信搜索公众号:就用python
|