Python 数据库操作 SQLAlchemy的示例代码
程序在运行过程中所有的的数据都存储在内存(RAM)中,「RAM是易失性存储器,系统掉电后RAM中的所有数据将全部丢失」。在大多数情况下我们希望程序运行中产生的数据能够长久的保存,此时我们就需要将数据保存到磁盘上,无论是保存到本地磁盘,还是通过网络保存到服务器上,最终都会将数据写入磁盘文件。将数据保存在磁盘中我们需要面对一个数据格式的问题,此时就需要引入数据库操作。
数据库是专门用于数据的集中存储和查询的软件,它便于程序保存和读取数据,且能够通过特定的条件查询指定的数据。
Python的标准数据库接口为PythonDB-API,它为编程人员提供了完善的数据库应用标称接口。但是使用PythonDB-API需要开发人员自行去拼接SQL,并把SQL做成模板。此时全靠编程人员来保证系统的安全性,完全有人来保证系统的安全性,不可避免的会出现错误,为了减少人为原因产生的错误ORM框架应运而生。
ORM即Object-RelationalMapping,把关系数据库的表结构映射到对象上面。负责这个转换过程的就是ORM框架
Python中的ORM框架主要有SQLObject、Storm、Django'sORM、peewee、SQLALchemy。每种ORM框架都有各自的特点和相应的应用范围,本文主要介绍SALALchemy,若你对其他框架感兴趣请自行搜索相关内容。
SQLAlchemy简介
SQLAlchemy是一个功能强大的开源PythonORM工具包。它提供了“一个知名企业级的持久化模式的,专为高效率和高性能的数据库访问设计的,改编成一个简单的Python域语言的完整套件”。它采用了数据映射模式(像Java中的Hibernate)而不是ActiveRecord模式(像RubyonRails的ORM)。
SQLAlchemy官网。
SQLAlchemy的优缺点:
优点:
- 企业级API,使得代码有健壮性和适应性。
- 灵活的设计,使得能轻松完成复杂的数据查询。
缺点:
- 工作单元概念不常见。
- 重量级API,导致长学习曲线。
SQLAlchemy应用
以下是一段使用SQLAlchemy操作SQLite数据库的代码
#-*-coding:utf-8-*- fromsqlalchemyimport( create_engine, Column, Integer, String, ) fromsqlalchemy.ext.declarativeimportdeclarative_base fromsqlalchemy.ormimportsessionmaker engine=create_engine('sqlite:///./sqlalchemy.sqlite',echo=True) Base=declarative_base() classUser(Base): __tablename__='users' id=Column(Integer,primary_key=True,autoincrement=True) name=Column(String) fullname=Column(String) nickname=Column(String) def__repr__(self): return""%(self.name,self.fullname,self.nickname) db_session=sessionmaker(bind=engine) session=db_session() Base.metadata.create_all(engine) user1=User(name='ed',fullname='EdJones',nickname='edsnickname') user2=User(name='wendy',fullname='WendyWilliams',nickname='windy') user3=User(name='mary',fullname='MaryContrary',nickname='mary') session.add(user1) session.add(user2) session.add(user3) session.commit() user=session.query(User).filter(User.id<2).all() print(user) user=session.query(User).filter(User.id<=5).all() print(user) user1.name='admin' session.merge(user1) user4=User(name='fred',fullname='FredFlintstone',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)
在以上代码中我们完成了一下工作:
- 连接到数据库「本次我们使用的是SQLite数据库」。
- 创建数据库表并将其映射到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会根据你选择的数据库配置而调用对应的DB-API。
create_engine函数并会不真正建立数据库的DB-API连接,当调用Engine.execute()或Engine.connect()方法时才会建立连接。大多数情况下我们无需关注Engine,SQLAlchemy会帮我们处理。
创建数据库表
将python类映射到数据库表上,这个Python类需要时一个指定基类的子类,这个基类应当含有ORM映射中相关的类和表的信息。这个基类可以通过declarative_base方法来创建。
Base=declarative_base()
在这个示例中使用Base基类创建了一个User的类来作为数据库表。
classUser(Base): __tablename__='users' id=Column(Integer,primary_key=True,autoincrement=True) name=Column(String) fullname=Column(String) nickname=Column(String) def__repr__(self): return""%(self.name,self.fullname,self.nickname)
在User类中我们定义了需要映射到数据库表上的属性,主要包括表名称、列的类型和名称等。这个类至少应包含一个名为tablename的属性来给出数据库表的名称,及至少一个给出表的主键「primarykey」的列。在User类中我们定义了表名称为users,定义了id、name、fullname、nickname四列数据,并设置id为表的主键。
创建完成User类后,实际在SQLite数据库中并不存在该表,此时需要使用declarative基类的Metadata.create_all在数据库中创建users表,在create_all方法中我们需要传入参数Engine。
通过Metadata.create_all传入的Engine参数,SQLAlchemy自动实现对数据库的连接。
Base.metadata.create_all(engine)
metadata.create_all方法执行完成后在SQLite数据库即可查到名称为users的数据表。
保存数据实例到数据库中
将数据保存到数据库中,我们需要User的实例和用于操作数据的session。
session是ORM数据的接口,可以通过session来操作数据库中的数据。
使用已经定义完成的User类将数据实例化。
user1=User(name='ed',fullname='EdJones',nickname='edsnickname') user2=User(name='wendy',fullname='WendyWilliams',nickname='windy') user3=User(name='mary',fullname='MaryContrary',nickname='mary')
获取session首先需要使用sessionmaker来得到session的工厂类,然后通过工厂类来获取session。
db_session=sessionmaker(bind=engine) session=db_session()
session通过Engine与数据库进行关联。session创建完成后并不会立即打开与数据库的连接,只有当我们第一使用session是,才会从Engine维护的连接池中取出一个连接来操作数据库,这个连接在我们关闭session时会被释放。
获取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)
以上代码通过query获取数据库中所有User数据,然后通过filter方法筛选出id小于2和id小于等于5的数据。
数据库的修改可以通过merge和update来实现
user1.name='admin' session.merge(user1) user4=User(name='fred',fullname='FredFlintstone',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)
使用merge修改数据,当数据中存在该数据时修改,不存在是将当前数据插入数据库中。
代码运行结果
以上示例代码的运行结果如下
2019-02-1621:45:23,919INFOsqlalchemy.engine.base.EngineSELECTCAST('testplainreturns'ASVARCHAR(60))ASanon_1 2019-02-1621:45:23,919INFOsqlalchemy.engine.base.Engine() 2019-02-1621:45:23,919INFOsqlalchemy.engine.base.EngineSELECTCAST('testunicodereturns'ASVARCHAR(60))ASanon_1 2019-02-1621:45:23,919INFOsqlalchemy.engine.base.Engine() 2019-02-1621:45:23,920INFOsqlalchemy.engine.base.EnginePRAGMAtable_info("users") 2019-02-1621:45:23,920INFOsqlalchemy.engine.base.Engine() 2019-02-1621:45:23,921INFOsqlalchemy.engine.base.Engine CREATETABLEusers( idINTEGERNOTNULL, nameVARCHAR, fullnameVARCHAR, nicknameVARCHAR, PRIMARYKEY(id) ) 2019-02-1621:45:23,921INFOsqlalchemy.engine.base.Engine() 2019-02-1621:45:23,922INFOsqlalchemy.engine.base.EngineCOMMIT 2019-02-1621:45:23,924INFOsqlalchemy.engine.base.EngineBEGIN(implicit) 2019-02-1621:45:23,925INFOsqlalchemy.engine.base.EngineINSERTINTOusers(name,fullname,nickname)VALUES(?,?,?) 2019-02-1621:45:23,925INFOsqlalchemy.engine.base.Engine('ed','EdJones','edsnickname') 2019-02-1621:45:23,926INFOsqlalchemy.engine.base.EngineINSERTINTOusers(name,fullname,nickname)VALUES(?,?,?) 2019-02-1621:45:23,926INFOsqlalchemy.engine.base.Engine('wendy','WendyWilliams','windy') 2019-02-1621:45:23,926INFOsqlalchemy.engine.base.EngineINSERTINTOusers(name,fullname,nickname)VALUES(?,?,?) 2019-02-1621:45:23,926INFOsqlalchemy.engine.base.Engine('mary','MaryContrary','mary') 2019-02-1621:45:23,927INFOsqlalchemy.engine.base.EngineCOMMIT 2019-02-1621:45:23,929INFOsqlalchemy.engine.base.EngineBEGIN(implicit) 2019-02-1621:45:23,929INFOsqlalchemy.engine.base.EngineSELECTusers.idASusers_id,users.nameASusers_name,users.fullnameASusers_fullname,users.nicknameASusers_nickname FROMusers WHEREusers.id 2019-02-1621:45:23,929INFOsqlalchemy.engine.base.Engine(2,) [] 2019-02-1621:45:23,931INFOsqlalchemy.engine.base.EngineSELECTusers.idASusers_id,users.nameASusers_name,users.fullnameASusers_fullname,users.nicknameASusers_nickname FROMusers WHEREusers.id<=? 2019-02-1621:45:23,931INFOsqlalchemy.engine.base.Engine(5,) [ , , ] 2019-02-1621:45:23,932INFOsqlalchemy.engine.base.EngineUPDATEusersSETname=?WHEREusers.id=? 2019-02-1621:45:23,932INFOsqlalchemy.engine.base.Engine('admin',1) 2019-02-1621:45:23,933INFOsqlalchemy.engine.base.EngineINSERTINTOusers(name,fullname,nickname)VALUES(?,?,?) 2019-02-1621:45:23,933INFOsqlalchemy.engine.base.Engine('fred','FredFlintstone','freddy') 2019-02-1621:45:23,934INFOsqlalchemy.engine.base.EngineUPDATEusersSETname=?WHEREusers.id=? 2019-02-1621:45:23,934INFOsqlalchemy.engine.base.Engine('test',2) 2019-02-1621:45:23,935INFOsqlalchemy.engine.base.EngineSELECTusers.idASusers_id,users.nameASusers_name,users.fullnameASusers_fullname,users.nicknameASusers_nickname FROMusers WHEREusers.id<=? 2019-02-1621:45:23,935INFOsqlalchemy.engine.base.Engine(5,) [ , , , ]
由于我们设置create_engine中echo为True,因此在执行结果中包含了SQLAlchemy打印的SQL语句,我们可以取消crete_engine中的echo
engine=create_engine('sqlite:///./sqlalchemy.sqlite')
此时的执行结果如下:
[] [ , , ] [ , , , ]
当取消echo后,程序运行结果中原有的SQL语句消失。
本文只是对SQLAlchemy的使用进行简单的介绍,SQLAlchemy本身还有很多特性和运用方法我们可以共同探讨。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。