ORM
ORM,对象关系映射,对象和关系之间的映射,使用面向对象的方式来操作数据库
关系模型和Python对象之间的映射
table => class ,表映射为类
row => object ,行映射为实例
column => property ,字段映射为属性
SQLAlchemy
安装
$ pip install sqlalchemy
文档
官方文档 http://docs.sqlalchemy.org/en/latest/
查看版本
import sqlalchemy
print(sqlalchemy.__version__)
开发
SQLAlchemy内部使用了连接池
创建连接
数据库连接的事情,交给引擎
from sqlalchemy import create_engine
dialect+driver://username:password@host:port/database
mysqldb的连接
mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
engine = sqlalchemy.create_engine("mysql+mysqldb://test:[email protected]:3306/test")
pymysql的连接
mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
engine = sqlalchemy.create_engine("mysql+pymysql://test:[email protected]:3306/test")
engine = sqlalchemy.create_engine("mysql+pymysql://test:[email protected]:3306/test",
echo=True)
echo=True
引擎是否打印执行的语句,调试的时候打开很方便。
lazy connecting:懒连接。创建引擎并不会马上连接数据库,直到让数据库执行任务时才连接。
Declare a Mapping创建映射
创建基类
from sqlalchemy.ext.declarative import declarative_base
# 创建基类,便于实体类继承。SQLAlchemy大量使用了元编程
Base = declarative_base() # 内部实现描述器
创建实体类
student表
CREATE TABLE student (
id INTEGER NOT NULL AUTO_INCREMENT,
name VARCHAR(64) NOT NULL,
age INTEGER,
PRIMARY KEY (id)
)
from sqlalchemy import Column, Integer, String
# 创建实体类
class Student(Base):
# 指定表名
__tablename__ = 'student'
# 定义类属性对应字段
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(64), nullable=False)
age = Column(Integer)
# 第一参数是字段名,如果和属性名不一致,一定要指定
# 例如:a = Column('age', Integer)
def __repr__(self):
return "{} id={} name={} age={}".format(
self.__class__.__name__, self.id, self.name, self.age)
# 查看表结构
print(Student)
print(repr(Student.__table__))
# 显示结果
Table('student', MetaData(bind=None),
Column('id', Integer(), table=<student>, primary_key=True, nullable=False),
Column('name', String(length=64), table=<student>, nullable=False),
Column('age', Integer(), table=<student>),
schema=None)
__tablename__
指定表名
Column类指定对应的字段,必须指定, 第一参数是字段名, 如果和属性名一致, 则不需要传参
实例化
s = Student(name='tom')
print(s.name)
s.age = 20
print(s.age)
创建表
可以使用SQLAlchemy来创建、删除表
# 删除继承自Base的所有表
Base.metadata.drop_all(engine)
# 创建继承自Base的所有表
Base.metadata.create_all(engine)
生产环境很少这样创建表,都是系统上线的时候由脚本生成。
生产环境很少删除表,宁可废弃都不能删除
创建会话session
在一个会话中操作数据库,会话建立在连接上,连接被引擎管理。
当第一次使用数据库时,从引擎维护的连接池中获取一个连接使用
# 创建session
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm.session import Session
# Session = sessionmaker(bind=engine) # 工厂方法返回类
session:Session = sessionmaker(bind=engine)() # 实例化
# 依然在第一次使用时连接数据库
session对象线程不安全。所以不同线程应该使用不用的session对象。
Session类和engine有一个就行了
CRUD操作
增
add():增加一个对象
add_all():可迭代对象,元素是对象
import sqlalchemy
from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
IP = "127.0.0.1" # IP
USERNAME = "test" # 用户名称
PASSWORD = "test" # 用户密码
DBNAME = "test" # 数据库名称
PORT = 3306 # 端口
# 用户名称, 密码, IP, 端口, 数据库名称
# 创建引擎
engine = create_engine("mysql+pymysql://{}:{}@{}:{}/{}".format(
USERNAME, PASSWORD, IP, PORT, DBNAME
),echo=True) # lazy 懒连接
# Base.metadata.drop_all(engine) # 删除Base管理的所有类对应的表
# Base.metadata.create_all(engine) # 创建Base管理的所有类对应的表
###########################################
# ORM Mapping 创建映射
Base = declarative_base() # 基类
# 内部实现描述器
class Student(Base):
__tablename__ = "student" # 表名称
# 定义字段类型和属性
id = Column(Integer, primary_key=True, autoincrement=True) # 第一个写字段名, 如果字段名和属性名相同, 则省略不写
name = Column(String(64), nullable=False)
age = Column(Integer)
def __repr__(self):
return "<{} id={}, name={}, age={}>".format(
__class__.__name__, self.id, self.name, self.age
)
# 创建会话
from sqlalchemy.orm.session import Session
# Session = sessionmaker(bind=engine) # 绑定engine, 工厂方法返回类
session:Session = sessionmaker(bind=engine)() # 线程不安全
#####################