博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQLAlchemy
阅读量:7240 次
发布时间:2019-06-29

本文共 11141 字,大约阅读时间需要 37 分钟。

一、CRM介绍

  数据库表是一个二维表,包含多行多列。把一个表的内容用Python的数据结构表示出来的话,可以用一个list表示多行,list的每一个元素是tuple,表示一行记录,比如,包含idnameuser表:

[    ('1', 'Michael'),    ('2', 'Bob'),    ('3', 'Adam')]

  Python的DB-API返回的数据结构就是像上面这样表示的。

  但是用tuple表示一行很难看出表的结构。如果把一个tuple用class实例来表示,就可以更容易地看出表的结构来:

class User(object):    def __init__(self, id, name):        self.id = id        self.name = name[    User('1', 'Michael'),    User('2', 'Bob'),    User('3', 'Adam')]

  这就是传说中的ORM技术:Object-Relational Mapping,把关系数据库的表结构映射到对象上。 

  在Python中,最有名的ORM框架是SQLAlchemy。

 

二、SqlAlchemy基本操作

  SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

 

    

  Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:  

MySQL-Python    mysql+mysqldb://
:
@
[:
]/
pymysql mysql+pymysql://
:
@
/
[?
] MySQL-Connector mysql+mysqlconnector://
:
@
[:
]/
cx_Oracle oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...] 更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html

  

  安装SQLAlchemy、mysql-connector

  pip  install SQLAlchemy

  pip  install --egg mysql-connector

 

  1、使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。    

#!/usr/bin/env python# -*- coding:utf-8 -*-  from sqlalchemy import create_engine  # 初始化数据库连接  engine = create_engine("mysql+mysqlconnector://root:123,.abc@127.0.0.1:3306/s12day9", max_overflow=5)  engine.execute(    "INSERT INTO test (id, name) VALUES ('2', 'Rambo')")  #engine.execute(#     "INSERT INTO test (a, b) VALUES (%s, %s)",#    ((555, "v1"),(666, "v1"),)#)#engine.execute(#    "INSERT INTO test (a, b) VALUES (%(id)s, %(name)s)",#    id=999, name="v1"#)  result = engine.execute('select * from test')result.fetchall()

  

  2、使用 Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 进行数据库操作。Engine使用Schema Type创建一个特定的结构对象,之后通过SQL Expression Language将该对象转换成SQL语句,然后通过 ConnectionPooling 连接数据库,再然后通过 Dialect 执行SQL,并获取结果。  

#!/usr/bin/env python# -*- coding:utf-8 -*-from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKeymetadata = MetaData()user = Table('users', metadata,    Column('id', Integer, primary_key=True),    Column('name', String(20)),)color = Table('color', metadata,    Column('id', Integer, primary_key=True),    Column('name', String(20)),)engine = create_engine("mysql+mysqlconnector://root:123,.abc@localhost:3306/s12day9", max_overflow=5)metadata.create_all(engine)

  增删改查

#!/usr/bin/env python# -*- coding:utf-8 -*-from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKey, selectmetadata = MetaData()user = Table('users', metadata,    Column('id', Integer, primary_key=True),    Column('name', String(20)),)color = Table('color', metadata,    Column('id', Integer, primary_key=True),    Column('name', String(20)),)engine = create_engine("mysql+mysqlconnector://root:123,.abc@127.0.0.1:3306/s12day9", max_overflow=5)conn = engine.connect()# 创建SQL语句,INSERT INTO "user" (id, name) VALUES (:id, :name)#conn.execute(user.insert(),{'id':1,'name':'flash'})#conn.close()# 插入数据的另一种方法#sql = user.insert().values(id=2, name='Rambo')#conn.execute(sql)#conn.close()# 删除id大于1的记录 #sql = user.delete().where(user.c.id > 1)#conn.execute(sql)#conn.close()sql = user.update().values(fullname=user.c.name)sql = user.update().where(user.c.name == 'jack').values(name='ed')sql = select([user, ])sql = select([user.c.id, ])sql = select([user.c.name, color.c.name]).where(user.c.id==color.c.id)sql = select([user.c.name]).order_by(user.c.name)sql = select([user]).group_by(user.c.name)result = conn.execute(sql)print(result.fetchall())conn.close()

 

   完整的例子:

#!/usr/bin/env python# -*- coding:utf-8 -*- # 导入from sqlalchemy import create_enginefrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy import Column, Integer, Stringfrom  sqlalchemy.orm import sessionmaker # 创建对象的基类Base = declarative_base() # 初始化数据库连接, echo为False表示不显示消息,为True则显示。engine = create_engine("mysql+mysqlconnector://root:123,.abc@localhost:3306/s12day9",echo=False)class Host(Base):   # 表的名字    __tablename__ = 'hosts'   # 表的结构    id = Column(Integer,primary_key=True,autoincrement=True)    hostname = Column(String(64),unique=True,nullable=False)    ip_addr = Column(String(128),unique=True,nullable=False)    port = Column(Integer,default=22)
# 生成一个SqlORM 基类 Base.metadata.create_all(engine)

  以上代码完成SQLAlchemy的初始化和具体每个表的class定义。如果有多个表,就继续定义其他class,例如app:

class app(Base):    __tablename__ = 'school'    id = ...    name = ...

  创建数据库会话,往数据库添加记录: 

if __name__ == '__main__':    # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例    SessionCls = sessionmaker(bind=engine)     session = SessionCls()    #h1 = Host(hostname='localhost',ip_addr='127.0.0.1')    h2 = Host(hostname='ubuntu',ip_addr='192.168.2.243',port=20000)    h3 = Host(hostname='ubuntu2',ip_addr='192.168.2.244',port=20000)    session.add(h3)             #将h3添加到session    #session.add_all( [h1,h2])  #批量添加     h2.hostname = 'ubuntu_test' #只要没提交,此时修改也没问题     #session.rollback()      # 创建Query查询,filter是where条件,最后调用all()返回所有行,调用one()则返回唯一行    # res=session.query(Host).filter(Host.hostname.in_(['ubuntu2','localhost'])).all()    # print(res)    ### 先查询后修改    #res = session.query(Host).filter(Host.hostname=="localhost").first()     #res.hostname = "test server"    ### 先查询后删除

         #res = session.query(Host).filter(Host.hostname=="test server").first()

         #session.delete(res)

session.commit() #提交  

更多内容详见:

    http://www.jianshu.com/p/e6bba189fcbd

    http://docs.sqlalchemy.org/en/latest/core/expression_api.html  

 

  3、使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 所有组件对数据进行操作。根据类创建对象,对象转换成SQL,执行SQL。 

#!/usr/bin/env python# -*- coding:utf-8 -*- from sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy import Column, Integer, Stringfrom sqlalchemy.orm import sessionmakerfrom sqlalchemy import create_engine engine = create_engine("mysql+mysqlconnector://root:123,.abc@127.0.0.1:3306/s12day9", max_overflow=5) Base = declarative_base()  class User(Base):    __tablename__ = 'users'    id = Column(Integer, primary_key=True)    name = Column(String(50)) # 寻找Base的所有子类,按照子类的结构在数据库中生成对应的数据表信息# Base.metadata.create_all(engine) Session = sessionmaker(bind=engine)session = Session()  # ########## 增 ########### u = User(id=2, name='sb')# session.add(u)# session.add_all([#     User(id=3, name='sb'),#     User(id=4, name='sb')# ])# session.commit() # ########## 删除 ########### session.query(User).filter(User.id > 2).delete()# session.commit() # ########## 修改 ########### session.query(User).filter(User.id > 2).update({'cluster_id' : 0})# session.commit()# ########## 查 ########### ret = session.query(User).filter_by(name='sb').first() # ret = session.query(User).filter_by(name='sb').all()# print ret # ret = session.query(User).filter(User.name.in_(['sb','bb'])).all()# print ret # ret = session.query(User.name.label('name_label')).all()# print ret,type(ret) # ret = session.query(User).order_by(User.id).all()# print ret # ret = session.query(User).order_by(User.id)[1:3]# print ret# session.commit()

  

三、外键关联

  由上面的例子可以看出,ORM就是把数据库表的行与相应的对象建立关联,互相转换。

  由于关系数据库的多个表还可以用外键实现一对多、多对多等关联,相应地,ORM框架也可以提供两个对象之间的一对多、多对多等功能。

  

  例如,如果一个Group拥有多个Host,就可以定义一对多(一个组可以对应多个主机,但一个主机只能对应一个组)关系如下:

class Host(Base):    __tablename__ = 'hosts'    id = Column(Integer,primary_key=True,autoincrement=True)    hostname = Column(String(64),unique=True,nullable=False)    ip_addr = Column(String(128),unique=True,nullable=False)    port = Column(Integer,default=22)    group_id = Column(Integer,ForeignKey('group.id'))     class Group(Base):    __tablename__ = 'group'    id = Column(Integer,primary_key=True)    name = Column(String(64),unique=True,nullable=False)    # host_id = Column(Integer,ForeignKey('host.id'))        # 如果host_id写在Group里,就相当于一对一了,一个组对应一台主机,所以一定要写在host里面

  

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3  4 from sqlalchemy import create_engine 5 from sqlalchemy import Table, Column, Integer, String, ForeignKey 6 from sqlalchemy.orm import relationship 7 from sqlalchemy.ext.declarative import declarative_base 8 from  sqlalchemy.orm import sessionmaker 9 10 Base = declarative_base()11 12 engine = create_engine("mysql+mysqlconnector://root:123,.abc@localhost:3306/s12day9",echo=True)13 14 15 class Host(Base):16     __tablename__ = 'hosts'17     id = Column(Integer,primary_key=True,autoincrement=True)18     hostname = Column(String(64),unique=True,nullable=False)19     ip_addr = Column(String(128),unique=True,nullable=False)20     port = Column(Integer,default=22)21     group_id = Column(Integer,ForeignKey('group.id'))22 23 class Group(Base):24     __tablename__ = 'group'25     id = Column(Integer,primary_key=True)26     name = Column(String(64),unique=True,nullable=False)27     # host_id = Column(Integer,ForeignKey('host.id'))28 29 Base.metadata.create_all(engine) #创建所有表结构30 31 if __name__ ==  '__main__':32     SessionCls = sessionmaker(bind=engine)33     session = SessionCls()34     session.commit()
一对多
2016-06-28 23:27:58,944 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'2016-06-28 23:27:58,944 INFO sqlalchemy.engine.base.Engine {}2016-06-28 23:27:58,951 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()2016-06-28 23:27:58,951 INFO sqlalchemy.engine.base.Engine {}2016-06-28 23:27:58,957 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_12016-06-28 23:27:58,957 INFO sqlalchemy.engine.base.Engine {}2016-06-28 23:27:58,961 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_12016-06-28 23:27:58,962 INFO sqlalchemy.engine.base.Engine {}2016-06-28 23:27:58,964 INFO sqlalchemy.engine.base.Engine DESCRIBE `hosts`2016-06-28 23:27:58,964 INFO sqlalchemy.engine.base.Engine {}2016-06-28 23:27:58,965 INFO sqlalchemy.engine.base.Engine ROLLBACK2016-06-28 23:27:58,967 INFO sqlalchemy.engine.base.Engine DESCRIBE `group`2016-06-28 23:27:58,967 INFO sqlalchemy.engine.base.Engine {}2016-06-28 23:27:58,969 INFO sqlalchemy.engine.base.Engine ROLLBACK2016-06-28 23:27:58,972 INFO sqlalchemy.engine.base.Engine CREATE TABLE `group` (	id INTEGER NOT NULL AUTO_INCREMENT, 	name VARCHAR(64) NOT NULL, 	PRIMARY KEY (id), 	UNIQUE (name))2016-06-28 23:27:58,972 INFO sqlalchemy.engine.base.Engine {}2016-06-28 23:27:59,018 INFO sqlalchemy.engine.base.Engine COMMIT2016-06-28 23:27:59,019 INFO sqlalchemy.engine.base.Engine CREATE TABLE hosts (	id INTEGER NOT NULL AUTO_INCREMENT, 	hostname VARCHAR(64) NOT NULL, 	ip_addr VARCHAR(128) NOT NULL, 	port INTEGER, 	group_id INTEGER, 	PRIMARY KEY (id), 	UNIQUE (hostname), 	UNIQUE (ip_addr), 	FOREIGN KEY(group_id) REFERENCES `group` (id))2016-06-28 23:27:59,019 INFO sqlalchemy.engine.base.Engine {}2016-06-28 23:27:59,064 INFO sqlalchemy.engine.base.Engine COMMIT

  注:SQLAlchemy无法修改表结构(如果需要可以使用SQLAlchemy开发者开源的另外一个软件Alembic来完成),所以这里先删除hosts表(测试环境)再重新创建。

 

更多功能参见文档,下载PDF

 

总结: 

  ORM框架的作用就是把数据库表的一行记录与一个对象互相做自动转换。

  正确使用ORM的前提是了解关系数据库的原理。

 

转载于:https://www.cnblogs.com/Rambotien/p/5624805.html

你可能感兴趣的文章
从上往下打印二叉树
查看>>
决策支持系统是什么?
查看>>
解压缩
查看>>
Linux中curl命令和wget命令的使用介绍与比较
查看>>
shell之awk 记录
查看>>
python内置数据结构之set
查看>>
function_score 之script_score
查看>>
ssh配置客户端免密钥到服务端
查看>>
启动PHP时提示初始化错误
查看>>
复杂recyclerView封装库
查看>>
Java通过POI为Excel添加数据验证
查看>>
140925左右发现的bash重大漏洞
查看>>
Animation 作为ImageView的背景
查看>>
mysql 主从备份实验
查看>>
CentOS下用命令查看IP地址
查看>>
LNMP编译安装遇到问题归总
查看>>
PHP的bbs实现之四--创建调查
查看>>
搭建windows下filezilla FTP服务器
查看>>
View6.2替换VCS和Composer服务器证书
查看>>
Android项目重构之路:实现篇
查看>>