赞
踩
目录
SQLAlchemy 是 Python SQL工具集和对象关系映射框架(ORM),为开发者提供了强大且灵活的数据库操作。
他提供了一整套著名的企业级持久化存储模式,具有高效、高性能的数据库访问设计,并适配于简单易用的 Python 语言。
上述描述来自SQLAlchemy官方网站,更多详情请查看链接
SQLAlchemy概念 | 对应数据库的概念 | 说明 |
Engine | 数据库连接 | 客户端连接数据库,需确认地址、用户等参数 |
Session | 数据库会话 | 数据库CRUD交互会话 |
Model | 表 | Model是ORM中的类定义,对应数据库中的表格 |
Column | 列 | Column是对象在定义时,用于指定数据表的列属性 |
Query | 查询 | 表示一次查询 |
SQLAlchemy 数据类型 | 数据库数据类型 | Python数据类型 | 备注 |
Integer | int | int | |
String | String | str | |
Text | text | str | |
Float | float | float | |
Boolean | tinyint | bool | |
Date | date | datetime.date | |
DateTime | datetime | datetime,datetime | |
Time | time | datetime.datetime |
- # 安装mysql数据库Python依赖包
- pip install pymysql
-
- # 安装ORM框架
- pip install SQLAlchemy
这里假设使用的是本地的MySQL数据库,数据库名 test, 数据表名 STUDENTS。
- from sqlalchemy import create_engine
-
- # 数据使用本地,用户名root, 密码123456,数据库名test,密码123456(我随便取的,开发时一定注意密码的复杂度问题)
- db_link = f'mysql+pymysql://root:123456@127.0.0.1:3306/test'
-
- # 获取数据库连接对象
- engine = create_engine(db_link)
-
-
- engine = create_engine(db_link,
- echo=True,
- pool_size=8,
- pool_recycle=60*30
- )
- # echo: 当设置为True时会将orm语句转化为sql语句打印,一般debug的时候可用
- # pool_size: 连接池的大小,默认为5个,设置为0时表示连接无限制
- # pool_recycle: 设置时间以限制数据库多久没连接自动断开
ORM的重要特点,就是我们操作表的时候就需要通过操作对象来实现,现在我们来创建一个类,以常见的学生表举例:
- from sqlalchemy import Column, String, Integer
- from sqlalchemy.ext.declarative import declarative_base
-
- # 创建对象的基类:
- Base = declarative_base()
-
-
- # 定义User对象:
- class Student(Base):
- # 表的名字:
- __tablename__ = 'STUDENTS'
-
-
-
- def __init__(self, name, age, gender):
- self.name = name
- self.age = age
- self.gender = gender
-
- # 表的结构:
- id = Column(name='stu_id', type_=Integer, primary_key=True, autoincrement=True)
- name = Column(name='stu_name', type_=String(20))
- age = Column(name='stu_age', type_=Integer)
- gender = Column(name='stu_gender', type_=String(20))
declarative_base()是sqlalchemy内部封装的一个方法,通过其构造一个基类,这个基类和它的子类,可以将Python类和数据库表关联映射起来。
数据库表模型类通过__tablename__和表关联起来,Column表示数据表的列。
如数据表已通过执行SQL语句创建,则忽略此步骤
- # 创建数据表
- Base.metadata.create_all(engine)
执行结果如图所示
获取session会话
sqlalchemy中使用session对象用于创建程序和数据库之间的会话,所有对象的载入和保存都需要通过session对象 。
通过sessionmaker调用创建一个session工厂,并关联Engine,以确保每个session都可以使用该Engine连接资源:
- from sqlalchemy.orm import sessionmaker
-
- # 创建session工厂
- session_factory= sessionmaker(bind=engine)
-
- # 创建 session 对象
- session = session_factory()
session对象的常见操作方法包括:
新增数据
- # 创建一个学生对象
- new_student = Student('John', 18, "Male")
- # 将新数据插入到数据库表中
- session.add(new_student)
- # 事务提交
- session.commit()
查询数据
简单数据查询,例如查询所有的学生数据:
session.query(Student)
需要注意的是,这里只构造Query,事实上并没有发送至数据库进行查询,只会在Query.get()、Query.all()、Query.one()以及Query.__iter__等具有“执行”语义的函数,才会真的去获取.所以完整的语句是:
- all_students = session.query(Student).all()
- print(len(all_students))
-
- # 由于数据库中只有一条数据,所以此处输出数据是 1
单数据表条件查询,例如,查询编号为1的学生信息
- # 单数据表条件查询,查询id为1的学生
- criteria_students = session.query(Student).filter_by(id=1).all()
- print(len(criteria_students))
-
- # 或
-
- # 单数据表条件查询,查询id为1的学生
- criteria_students = session.query(Student).filter(Student.id == 1).all()
- print(len(criteria_students))
query有filter和filter_by两个过滤方法,通常这两个方法都会用到的,所以一定要掌握它们的区别:
filter | filter_by |
支持所有比较运算符,等值比较用 == | 只能使用 = ,!= , >, < |
过滤条件使用 类名.属性名 的形式 | 过滤条件使用 属性名 |
不支持组合查询,只能连续调用filter变相实现 | 参数是 **kwargs,支持组合查询 |
支持and、or和in等操作 |
修改数据
数据修改操作同样有两种方式,批量修改或同时需要修改多个属性时,例如同时修改age和gender(举个栗子),直接使用第一种方法传入字典数据即可{ "age" : 20, "gender" : "Female" }
- # 第一种修改方式
- session.query(Student).filter_by(id=1).update({"age": 20})
- session.commit()
-
- # 第二种修改方式
- stu = session.query(Student).filter_by(id=1).first()
- stu.age = 20
- session.add(stu)
- session.commit()
删除数据
- # 第一种删除方式
- del_stu = session.query(Student).filter_by(id=1).first()
- if del_stu:
- session.delete(del_stu)
- session.commit()
-
-
- # 第二种删除方式
- session.query(Student).filter_by(id=1).delete()
- session.commit()
以上就是SQLAlchemy的简单增删改查操作了。示例源码放在下面:
- # -*- coding: UTF-8 -*-
- from sqlalchemy import create_engine
-
- from student import Base, Student
- from sqlalchemy.orm import sessionmaker
-
- db_link = f'mysql+pymysql://root:aoto123@192.168.1.124:3306/test'
- engine = create_engine(db_link)
-
- print(engine)
-
- # 创建数据表
- # Base.metadata.create_all(engine)
-
- # 创建session
- DbSession = sessionmaker(bind=engine)
- session = DbSession()
-
- # 创建一个学生对象
- # new_student = Student('John', 18, "Male")
- # 将新数据插入到数据库表中
- # session.add(new_student)
- # 事务提交
- # session.commit()
-
- # 查询所有的学生数据
- all_students = session.query(Student).all()
- print(len(all_students))
-
- # 单数据表条件查询,查询id为1的学生
- # criteria_students = session.query(Student).filter_by(id=1).all()
- # print(len(criteria_students))
-
- # 单数据表条件查询,查询id为1的学生
- # criteria_students = session.query(Student).filter(Student.id == 1).all()
- # print(len(criteria_students))
-
- # 第一种修改方式
- # session.query(Student).filter_by(id=1).update({"age": 20})
- # session.commit()
-
- # 第二种修改方式
- # stu = session.query(Student).filter_by(id=1).first()
- # stu.age = 20
- # session.add(stu)
- # session.commit()
-
- # 第一种删除方式
- # del_stu = session.query(Student).filter_by(id=1).first()
- # if del_stu:
- # session.delete(del_stu)
- # session.commit()
-
- # 第二种删除方式
- # session.query(Student).filter_by(id=1).delete()
- # session.commit()
上述代码中关于Student的数据增删改查,类与查询条件的耦合度较高,用于项目中大量使用的话会造成代码比较混乱,这里分享一个简单封装的操作类,水平一般,仅供参考
- # -*- coding: UTF-8 -*-
-
- class DatabaseUtil(object):
-
- def __init__(self, session):
- """
- 初始化工具类
- :param session: 数据库连接会话
- """
- self.db_session = session
-
- def add_obj(self, obj):
- """
- 插入数据
- :param obj: 插入到数据库表记录的映射对象
- :return:
- """
- self.db_session.add(obj)
- # 提交即保存到数据库:
- self.db_session.commit()
-
- def del_obj(self, class_, *args):
- """
- 删除数据库记录
- :param class_: 数据表所对应的对象类型
- :param args: 筛选条件,元组类型
- :return:
- """
- self.db_session.query(class_).filter(args[0] == args[1]).delete()
- self.db_session.commit()
-
- def is_obj_exists(self, class_, *args):
- """
- 查询数据库中是否有数据记录
- :param class_: 数据表所对应的对象类型
- :param args: 筛选条件,元组类型
- :return: 有记录,返回True,否则返回False
- """
- obj_list = self.db_session.query(class_).filter(args[0] == args[1]).all()
- if len(obj_list) > 0:
- return True
- else:
- return False
-
- def insert_or_update(self, class_, *args, **kwargs):
- """
- 插入或更新一条记录
- :param class_: 数据表所对应的对象类型
- :param args: 筛选条件,元组类型
- :param kwargs: 插入到数据库中的数据记录,字典类型
- :return:
- """
- if self.is_obj_exists(class_, *args):
- # update
- self.db_session.query(class_).filter(args[0] == args[1]).update(kwargs)
- self.db_session.commit()
- else:
- # insert
- obj = class_(**kwargs)
- self.add_obj(obj)
-
-
- @staticmethod
- def props(obj):
- """
- 将class转dict,以_开头的属性不要
- :param obj:
- :return:
- """
- pr = {}
- for name in dir(obj):
- value = getattr(obj, name)
- if value is None:
- continue
- if not name.startswith('_') and not callable(value):
- pr[name] = value
- return pr
那么这个工具类如何使用呢,这里有个使用示例,请注意,这个工具类在初始化时,直接接收session值作为属性成员,您也可以在工具类直接接收数据库连接参数等数据,自己生成session会话。
在使用前,修改一下实体类的构造方法,直接转字典类型为class类型,方便操作,如下:
- from sqlalchemy import Column, String, Integer
- from sqlalchemy.ext.declarative import declarative_base
-
- # 创建对象的基类:
- Base = declarative_base()
-
-
- # 定义User对象:
- class Student(Base):
- # 表的名字:
- __tablename__ = 'STUDENTS'
-
- def __init__(self, **entries):
- self.__dict__.update(entries)
-
- # 表的结构:
- id = Column(name='stu_id', type_=Integer, primary_key=True, autoincrement=True)
- name = Column(name='stu_name', type_=String(20))
- age = Column(name='stu_age', type_=Integer)
- gender = Column(name='stu_gender', type_=String(20))
- from sqlalchemy import create_engine
- from sqlalchemy.orm import sessionmaker
-
- from database_test.db_utils import DatabaseUtil
- from student import Student
-
- if __name__ == '__main__':
- stu_info_1 = {"name": "John", "age": 18, "gender": "Male"}
- stu_info_2 = {"name": "Gina", "age": 20, "gender": "Female"}
- stu_info_3 = {"name": "Tom", "age": 23, "gender": "Male"}
-
- db_link = f'mysql+pymysql://root:aoto123@192.168.1.124:3306/test'
- engine = create_engine(db_link)
-
- # 创建session
- DbSession = sessionmaker(bind=engine)
- session = DbSession()
-
- # 获取工具对象
- db_util = DatabaseUtil(session)
- # 字典数据转换为Student对象
- new_stu = Student(**stu_info_1)
- # 新增
- db_util.add_obj(new_stu)
-
- # 新增或更新数据
-
- # 设置查询条件,等同于 where name = "some name" 和 query(Student).filter(name='some name')
- criteria = (Student.name, stu_info_1["name"])
- # 传入参数,如果这条记录不存在,插入数据,如果已存在,按照传入的数据更新
- db_util.insert_or_update(Student, *criteria, **stu_info_1)
-
- # 删除数据
- # 设置查询条件,等同于delete ... where name = "some name"
- db_util.del_obj(Student, *criteria)
-
- exit(0)
以上代码仅供参考,水平有限,欢迎各位批评指正。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。