Code前端首页关于Code前端联系我们

Python 数据库操作 SQLAlchemy 示例代码

terry 2年前 (2023-09-25) 阅读数 52 #后端开发

程序运行过程中所有数据都存储在内存(RAM)中。 “RAM是易失性存储器,系统关闭后RAM中的所有数据都会丢失。”大多数情况下,我们希望程序运行过程中产生的数据能够长期保存。这时,我们需要将数据保存在磁盘上,无论是存储在本地磁盘上,还是通过网络存储在服务器上,数据最终都会被写入磁盘文件中。要将数据保存到磁盘,我们必须面对数据格式问题。这时候我们就需要引入数据库操作。

数据库是专门用于集中存储和检索数据的软件。它方便程序存储和读取数据,并且可以通过特定的条件请求指定的数据。

Python的标准数据库接口是Python DB-API,它为程序员提供了数据库应用的完整名义接口。然而,使用Python的DB API需要开发人员自己链接SQL并将SQL变成模板。这时,就完全由程序员来保证系统的安全了。完全有人来保证系统的安全。错误不可避免地会发生。为了减少人为原因造成的错误,ORM框架应运而生。

ORM 是对象关系映射,它将关系数据库的表结构映射到对象。负责这个转换过程的ORM框架

Python中的ORM框架主要有SQLObject、Storm、Django的ORM、peewee和SQLALchemy。每个ORM框架都有自己的特点和相应的应用范围。本文主要介绍SALAL化学。如果您对其他框架感兴趣,请搜索。相关内容本身。

SQLAlchemy 简介

SQLAlchemy 是一个功能强大的开源 Python ORM 工具包。它提供了“一整套著名的企业级持久性模式,专为高效和高性能的数据库访问而设计,并适应于简单的Python领域语言。”它使用数据映射模式(如 Java 中的 Hibernate)而不是 Active Record 模式(如 Ruby on Rails 的 ORM)。

SQLAlchemy 官方网站。

SQLAlchemy 优缺点:

优点:

  • 企业级 API,使代码变得健壮且适应性强。
  • 灵活的设计可以轻松填写​​复杂的数据查询。

缺点:

  • 工作理念不统一。
  • 重量级API,导致学习曲线较长。 ?
  • 创建数据库表并将它们映射到 Python 类。
  • 创建数据实例并将其保存到数据库中。
  • 读取和更改数据库中存储的数据。
  • 导入SQLAlchemy模块并连接到SQLite数据库

    SQLAlchemy通过create_engine函数创建数据库连接。 create_engine函数的第一个参数是数据URL,第二个参数echo设置为True,这意味着我们可以在程序运行时在控制台上看到操作所涉及的SQL语句。

    本例中我们使用的数据库是SQLite,但您也可以使用其他数据库。仅在调试状态下将 echo 设置为 true。在生产环境中,请设置echo 为 false 或保留 echo 参数。

engine = create_engine('sqlite:///./sqlalchemy.sqlite', echo=True)

create_engine 返回一个 Engine 实例,该实例指向数据库的一些核心接口。 SQLAlchemy 将根据您选择的数据库配置调用适当的数据库 API。

create_engine 函数不会创建与数据库的 DB-API 连接。仅当调用 Engine.execute() 或 Engine.connect() 方法时才会建立连接。大多数情况下我们不需要关注引擎,SQLAlchemy 会帮我们处理。

创建数据库表

将 Python 类映射到数据库表。此 Python 类必须是指定基类的子类。这个基类应该包含ORM映射中相应的类和表信息。该基类可以通过 declarative_base 方法创建。
Base = declarative_base()

在此示例中,Base Base 类用于创建 User 类作为数据库表。

class User(Base):
  __tablename__ = 'users'

  id = Column(Integer, primary_key=True, autoincrement=True)
  name = Column(String)
  fullname = Column(String)
  nickname = Column(String)

  def __repr__(self):
    return "<User(name='%s', fullname='%s', nickname='%s')>" % (self.name, self.fullname, self.nickname)

在User类中我们定义了必须映射到数据库表的属性,主要是表名、列类型和名称等。此类应至少包含一个名为 tablename 的属性(给出数据库表的名称),以及至少一列给出表的主键。在user类中,我们定义表名为user,定义四列数据:ID、姓名、全名、昵称,并将ID设置为表的主键。
创建用户类后,SQLite数据库中实际上并不存在该表。这时就需要使用声明性基类的Metadata.create_all在数据库中创建用户表。在create_all方法中我们需要传递Engine参数。

SQLAlchemy 通过 Metadata.create_all 中传递的 Engine 参数自动连接数据库。

Base.metadata.create_all(engine)

执行metadata.create_all方法后,可以在SQLite数据库中找到名为user的数据表。

将数据实例保存到数据库

将数据保存到数据库,我们需要一个用户的实例和一个用于操作数据的会话。

Session是ORM数据的接口。可以通过session来操作数据库中的数据。

使用已经定义的用户类来实例化数据。

user1 = User(name='ed', fullname='Ed Jones', nickname='edsnickname')
user2 = User(name='wendy', fullname='Wendy Williams', nickname='windy')
user3 = User(name='mary', fullname='Mary Contrary', nickname='mary')

获取session首先要使用sessionmaker获取session工厂类,然后通过工厂类获取session。

db_session = sessionmaker(bind=engine)
session = db_session()

Session通过Engine连接到数据库。创建会话后,并不会立即打开与数据库的连接。只有当我们第一次使用session时,才会从引擎维护的连接池中取出一个连接来操作数据库。当我们关闭会话时,该连接将被释放。
收到会话后,您可以使用 Add 和 Commit 方法将数据保存到数据库中。

session.add(user1)
session.add(user2)
session.add(user3)
session.commit()

查询和更改数据库中的数据

SQLAlchemy使用query来查询数据,查询结果可以通过filter方法进行过滤。

user = session.query(User).filter(User.id<2).all()
print(user)
user = session.query(User).filter(User.id<=5).all()
print(user)

上面的代码通过查询的方式获取数据库中的所有用户数据,然后通过filter方法过滤掉ID小于2和ID小于等于5的数据。

可以通过合并和更新来实现数据库的修改

user1.name = 'admin'
session.merge(user1)
user4 = User(name='fred', fullname='Fred Flintstone', nickname='freddy')
session.merge(user4)
session.query(User).filter(User.id==2).update({'name':'test'})
user = session.query(User).filter(User.id<=5).all()
print(user)

使用合并来修改数据。如果数据中存在该数据,则会发生更改。如果不存在,则将当前数据插入到数据库中。

代码运行结果

上面示例代码的运行结果如下

2019-02-16 21:45:23,919 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2019-02-16 21:45:23,919 INFO sqlalchemy.engine.base.Engine ()
2019-02-16 21:45:23,919 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2019-02-16 21:45:23,919 INFO sqlalchemy.engine.base.Engine ()
2019-02-16 21:45:23,920 INFO sqlalchemy.engine.base.Engine PRAGMA table_info("users")
2019-02-16 21:45:23,920 INFO sqlalchemy.engine.base.Engine ()
2019-02-16 21:45:23,921 INFO sqlalchemy.engine.base.Engine
CREATE TABLE users (
  id INTEGER NOT NULL,
  name VARCHAR,
  fullname VARCHAR,
  nickname VARCHAR,
  PRIMARY KEY (id)
)


2019-02-16 21:45:23,921 INFO sqlalchemy.engine.base.Engine ()
2019-02-16 21:45:23,922 INFO sqlalchemy.engine.base.Engine COMMIT
2019-02-16 21:45:23,924 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-02-16 21:45:23,925 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name, fullname, nickname) VALUES (?, ?, ?)
2019-02-16 21:45:23,925 INFO sqlalchemy.engine.base.Engine ('ed', 'Ed Jones', 'edsnickname')
2019-02-16 21:45:23,926 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name, fullname, nickname) VALUES (?, ?, ?)
2019-02-16 21:45:23,926 INFO sqlalchemy.engine.base.Engine ('wendy', 'Wendy Williams', 'windy')
2019-02-16 21:45:23,926 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name, fullname, nickname) VALUES (?, ?, ?)
2019-02-16 21:45:23,926 INFO sqlalchemy.engine.base.Engine ('mary', 'Mary Contrary', 'mary')
2019-02-16 21:45:23,927 INFO sqlalchemy.engine.base.Engine COMMIT
2019-02-16 21:45:23,929 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-02-16 21:45:23,929 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.nickname AS users_nickname
FROM users
WHERE users.id < ?
2019-02-16 21:45:23,929 INFO sqlalchemy.engine.base.Engine (2,)
[<User(name='ed', fullname='Ed Jones', nickname='edsnickname')>]
2019-02-16 21:45:23,931 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.nickname AS users_nickname
FROM users
WHERE users.id <= ?
2019-02-16 21:45:23,931 INFO sqlalchemy.engine.base.Engine (5,)
[<User(name='ed', fullname='Ed Jones', nickname='edsnickname')>, <User(name='wendy', fullname='Wendy Williams', nickname='windy')>, <User(name='mary', fullname='Mary Contrary', nickname='mary')>]
2019-02-16 21:45:23,932 INFO sqlalchemy.engine.base.Engine UPDATE users SET name=? WHERE users.id = ?
2019-02-16 21:45:23,932 INFO sqlalchemy.engine.base.Engine ('admin', 1)
2019-02-16 21:45:23,933 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name, fullname, nickname) VALUES (?, ?, ?)
2019-02-16 21:45:23,933 INFO sqlalchemy.engine.base.Engine ('fred', 'Fred Flintstone', 'freddy')
2019-02-16 21:45:23,934 INFO sqlalchemy.engine.base.Engine UPDATE users SET name=? WHERE users.id = ?
2019-02-16 21:45:23,934 INFO sqlalchemy.engine.base.Engine ('test', 2)
2019-02-16 21:45:23,935 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.nickname AS users_nickname
FROM users
WHERE users.id <= ?
2019-02-16 21:45:23,935 INFO sqlalchemy.engine.base.Engine (5,)
[<User(name='admin', fullname='Ed Jones', nickname='edsnickname')>, <User(name='test', fullname='Wendy Williams', nickname='windy')>, <User(name='mary', fullname='Mary Contrary', nickname='mary')>, <User(name='fred', fullname='Fred Flintstone', nickname='freddy')>]

因为我们将create_engine中的echo设置为True,所以执行结果中包含了SQLAlchemy打印的SQL语句。我们可以在crete_engine中取消echo

engine = create_engine('sqlite:///./sqlalchemy.sqlite')

此时的执行结果如下:

[<User(name='ed', fullname='Ed Jones', nickname='edsnickname')>]
[<User(name='ed', fullname='Ed Jones', nickname='edsnickname')>, <User(name='wendy', fullname='Wendy Williams', nickname='windy')>, <User(name='mary', fullname='Mary Contrary', nickname='mary')>]
[<User(name='admin', fullname='Ed Jones', nickname='edsnickname')>, <User(name='test', fullname='Wendy Williams', nickname='windy')>, <User(name='mary', fullname='Mary Contrary', nickname='mary')>, <User(name='fred', fullname='Fred Flintstone', nickname='freddy')>]

取消echo后,原来的SQL语句在程序执行结果中就消失了。

本文只是简单介绍一下SQLAlchemy的使用。 SQLAlchemy本身有很多功能和应用方法,我们可以一起讨论。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门