SqlAlchemy ORM
ORM的解释;
简单点:对象关系映射.
需求:我们写一个主机管理,把主机信息存在数据库,一开始我们编程不熟练的时候,执行命令时候要调用数据库,会把相应的SQL语句写到代码中,这种叫做hard coding(硬生生的代码),那么随着程序越来越复杂我们要写的sql语句也越来越多,那么代码中就会出现很多原生的sql语句通过调用数据API(如pymysql,mysql-python)来操作数据库.
并且好多原生的语句是不能重用的,你会发现你在程序的好多地方调用了重复的sql语句.当然,聪明的我们会想到,把这些重复的sql语句,写成函数.但是问题在于你在机在开始开发程序的时候,你没有办法完全预料到所有的操作场景,也就是说没办法预料到要用到什么样的sql语句.所以你还会在实际编程中写很多原生的SQL语句(写死了),并且不能重用.
另外开发人员写出来的sql语句肯定有一些低效率的语句,必定不是专业的DBA.并且如果涉及到多个表查询和做分类的聚合,sql语句如果不优化效率就非常低,所以一般的情况下,DBA会把复杂的sql语句封装成存储过程,让程序员调用.
但是还是有问题,假如现在把存储过程写到代码里,你们公司说我们要把mysql换成oracle,程序员傻逼了,程序里面好多原生的sql和存储过程调用,mysql和oracle语法有很多不一样的地方,那么怎么搞,只能全部重写掉sql语句.
你可能说,我写代码的时候会要求自己写成封装,但是一个项目好多人参与,其他人你能要求,但是万一他在快离职的时候就写一些原生的sql语句,你能怎样,不可控.而且对于个人来说,你封装的sql语句也仅限于当前使用的数据库类型,如果像上面提到的mysql切换成oracle,你就要该封装程序了.
总之,这种方式不可控,而且复杂,完了,这个问题按照自己写代码解决的思路不能解决了.当然我们花上1~3个月来写一个sql的封装的程序,那么我告诉你,可以,你写的就是类似ORM框架的东西,而且90%的可能性,你写的没有SqlAlchemy好.
所以我们最明智的做法是了解SqlAlchemy框架,并且熟练使用他. 下面我们来了解SqlAlchemy是怎么真正的帮我们实现的.
SQLAlcchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简而言之:将对象转化成SQL,然后使用数据API执行SQL并获取执行结果

    之前我们学过数据库的API如mysqldb-python直接写sql原生语句,sqlalchemy是建立在数据库API之上,对原生sql语句进行了封装,也就是说你用了sqlalchemy之后,你就不用写sql语句了,你不用写了,这就隔离了.你看看单独这一点就把前面我们遇到的在代码中写原生sql语句的问题解决了,因为你不用写sql语句了嘛.
那你会说代码中原生sql代码的问题解决了,那如何解决从mysql切换到oracle呢?接下来的dialect会根据你配置的不同的数据库类型来调用sqlalchemy内部定义的对于不同数据库类型的api接口.至于你担心的我之前调用的是mysql,现在是oracle的问题,sqlalchemy内部在实例化engine时,根据你连接的数据库类型来选择封装成什么类型的sql原生语句.
紧接着你会问支持多少种数据类型.往下看
(我个人理解的思路是我们知道mysql也好oracle也好,使用的语法会有些不同,那sqlalchemy就像一个中间件,源头是mysql或者oracle又或者是其他的数据库,经过sqlalchemy那么一封装,变成了对于python来说统一的调用模式.就那么简单)
  对上图的具体解释:
SQLALchemy ORM: 就是它的ORM,是对象封装的过程,它把sql语句封装成对象了,他这个对象是怎么封装的?不是说一连上sqlalchemy,就把数据库里所有的东西都封装了,而是你自己要声明,我要把这个表封装成什么对象,把那个表封装成什么对象.整个过程 1.先把原生的表映射成类.2.然后才能通过对象的形势调用它.
schema/Types: 你怎么进行对象关系映射?定义了一种映射格式,就是说你要把这个表映射成这个类,就通过这个框架格式
SQL Expression Language:增删改查的SQL封装语句.
Engine: 封装后你需要通过一个引擎操作它
connection pooling:连接池
Dialect:根据你的配置文件,连接不同的数据库
DBAPI:具体的API,mysql api或者oracle api

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

MySQL-Python
    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
  
pymysql
    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
  
MySQL-Connector
    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
  
cx_Oracle
    oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
  
更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html
案例一:
使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。
     #!/usr/bin/env python
# -*- coding:utf- -*- from sqlalchemy import create_engine engine = create_engine("mysql+mysqldb://root:123@127.0.0.1:3306/s11", max_overflow=) engine.execute(
"INSERT INTO ts_test (a, b) VALUES ('2', 'v1')"
) engine.execute(
"INSERT INTO ts_test (a, b) VALUES (%s, %s)",
((, "v1"),(, "v1"),)
)
engine.execute(
"INSERT INTO ts_test (a, b) VALUES (%(id)s, %(name)s)",
id=, name="v1"
) result = engine.execute('select * from ts_test')
result.fetchall()

  总结:使用sqlalchemy可以像使用数据库api一样直接调用原生代码。这种方式没有什么意义,我们只需要知道可以这么做即可。


步骤二sqlalchemy使用的中间状态:

使用 Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 进行数据库操作。
Engine使用Schema Type创建一个特定的结构对象,之后通过SQL Expression Language将该对象转换成SQL语句,然后通过 ConnectionPooling 连接数据库,再然后通过 Dialect 执行SQL,并获取结果。
 #!/usr/bin/env python3.
#__author__:'ted.zhou'
'''
sqlalchemy 的用法案例
使用 Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 进行数据库操作
'''
#!/usr/bin/env python
# -*- coding:utf- -*- from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKey
# 老师:MetaData需要理解下,就是在创建类时,sqlalchemy在MetaData里封装了好多的关于这个类的一些属性.包括怎么把Column,Integer,String,Table等等,转成相应的语句.
# 网络上资料解释: MetaData是元数据,元数据就是描述数据的数据,比如小明 身高:175cm,身高就是元数据,175cm就是实际数据.而在sqlalchemy里的MetaData实例化一个对象,就是一个元数据对象,里面具体的元数据有表名Table,列名Column,以及怎么把Column,Integer,String,Table等等,转成相应的语句方法名称.
# 总之,元数据必须有
metadata = MetaData() # 实例化一个属性对象
user = Table('user', metadata, # 实例化一个Table,并和metadata进行绑定.这些表的信息都属于metadata里的.
Column('id', Integer, primary_key=True),
Column('name', String()),
) color = Table('color', metadata,
Column('id', Integer, primary_key=True),
Column('name', String()),
)
# engine = create_engine("mysql+mysqldb://root:123.com@localhost:3306/test", max_overflow=) engine = create_engine("mysql+pymysql://root:123456@localhost:3307/test",max_overflow=,echo=True) # 创建一个连接引擎
# create_engine("数据库类型+数据库驱动://数据库用户名:数据库密码@IP地址:端口/数据库",其他参数)
# 上文当中echo=True是开启调试,这样当我们执行文件的时候会提示相应的文字。 metadata.create_all(engine)
#
# 这一步的具体执行内容就是下面说的.
# Engine使用Schema Type创建一个特定的结构对象,之后通过SQL Expression Language将该对象转换成SQL语句,然后通过 ConnectionPooling 连接数据库,再然后通过 Dialect 执行SQL,并获取结果。
步骤二sqlalchemy使用的中间状态的增删改查语法:
(建议只参考下,不需要记住,因为我们最终不会使用这种状态)
 #!/usr/bin/env python
# -*- coding:utf- -*- from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKey metadata = MetaData() # 实例化元数据对象
# 创建表结构,我个人的理解是这里的创建相当于在python的sqlalchemy中虚拟一个表结构,如果数据库中有相应的表,那么不会在数据库中创建,如果实际数据库中没有,那么需要通过metadata.create_all(engine)来创建,可参见案例一
# 所以可知,创建表结构有两个功能:.不紧可以声明元数据 .而且可以用来在数据库中创建表.
user = Table('user', metadata, Column('id', Integer, primary_key=True),
Column('name', String()),
) color = Table('color', metadata,
Column('id', Integer, primary_key=True),
Column('name', String()),
) # 实例化引擎,只是把连接信息作为参数传入,并未真的连接,要真的连接需要调用connect方法
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3307/test",echo=True) conn = engine.connect() # 引擎执行connect()方法,连接到数据库,获取到光标(游标) # 创建SQL语句,INSERT INTO "user" (id, name) VALUES (:id, :name)
conn.execute(user.insert(),{'id':,'name':'seven'}) # 这里我们之所以可以使用user.insert()进行数据插入,而不用写原生sql,是因为我们前面做了将user变量加入到了元数据实例metadata中,这样metadata才知道怎样将user.insert这段代码转化成对应的存储引擎的sql语句
# 所以说metadata必须加
conn.close() # 插入
# sql = user.insert().values(id=, name='wu') # user表
# conn.execute(sql)
# conn.close() # 删除
# sql = user.delete().where(user.c.id > ) # user.c.id # 改
# sql = user.update().values(fullname=user.c.name)
# sql = user.update().where(user.c.name == 'jack').values(name='ed') # 查询,查询和上面的插入,删除,改不一样,他使用单独的select方法,不需要像user.select,原因是查询的时候有时候会进行外连接,不是只针对一个表进行的.所以从实际出发sqlalchemy模块中有一个单独的select方法
# sql = select([user, ]) # 查询所有
# sql = select([user.c.id, ]) # 查字段
# sql = select([user.c.name, color.c.name]).where(user.c.id==color.c.id) # 查字段,设置where条件
# 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()

接下来,我们就看看实际编程中我们使用sqlalchemy的终极状态案例:

SqlAlchemy完整的例子(简单)_用法的终极状态.py
 #!/usr/bin/env python3.
#__author__:ted.zhou
import pymysql
from sqlalchemy import create_engine # 导入引擎类
from sqlalchemy.ext.declarative import declarative_base # 导入sqlalchemy的一个扩展模块declarative_base,此模块调用返回一个封装好的 metadata元数据和表名以及表字段 的类.注意返回的是个类,不是实例.
from sqlalchemy import Column,Integer,String # 导入和创建表结构相关的模块
from sqlalchemy.orm import sessionmaker # 导入sessionmaker模块,它自己是一个类,实例化它返回的还是一个类(是一个包含了数据库API信息和连接地址端口以及用户名和密码信息的类)不是一个实例
# 这句话的意思,拿到数据库API(传入的bind=engine参数作中记录了数据库的API和连接信息),创建一个连接的类.这个类里有连接信息,和数据库API信息,接下来要创建一个连接session就要实例化这个类 '''
使用sqlalchemy ORM完成对数据库的操作整个代码实现过程,可以理解成如下:
.如果想用sqlalchemy来操作数据库中的表,就需要把数据库的表结构映射成SqlORM类,这里请注意,一个SqlORM类实际上操作数据库的单位不是库,而是表,因为连接的时候直接选择到库.
.把表结构映射出去后,sqlalchemy内部需要一个内部映射的规则比如表名怎么映射,字段怎么映射,String类型怎么映射,Integer怎么映射,删除怎么搞等等,也就是前面说的元数据metadata ,元数据和映射后的表结构绑定后,就可以操作这张表(增删改查).
这里是使用declarative_base模块将前两步需要做的事情封装到一个类中.然后下面要创建的SqlORM子类就要继承这个基类了. 封装了映射方法和元数据方法的模块就是declarative_base
.上面两部完成后是只是说可以对映射的数据表进行操作了,但是操作是在本地的,你需要通过连接把SqlORM中的操作最终翻译成对应数据库类型的原生SQL语句,在调用数据库API进行操作. 那么这个引擎的实现模块就是create_engine
那么这个连接信息我们称之为引擎.
.引擎相当于一个连接工具,那么谁来使用这个引擎来对数据进行操作呢? 那就是session,session通过引擎调用一系列映射后的表的操作方法,然后翻译成原生SQL后调用数据库API.最终完成对数据库的操作.这个实现session的模块即是sessionmaker
''' Base = declarative_base() #生成一个SqlORM基类,接下来所有要创建的SqlORM的子类(理解成如果想用sqlalchemy来操作数据库中的表,就需要把数据库的表结构映射成SqlORM类) # 实例化引擎,只是把连接信息作为参数传入,并未真的连接.
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3307/test",echo=True) # echo=True可以显示转化后的原生SQL语句执行过程 class Host(Base): # 定义一个SqlORM类,继承Base类这样他就默认绑定了matedata和数据结构
__tablename__ = 'hosts' # 声明表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False) # 声明字段id,类型为int,为主键,自增长属性为真
hostname = Column(String(),unique=True,nullable=False) # 声明字段hostname,类型为String,是否唯一限制为True,是否可为空False
ip_addr = Column(String(),unique=True,nullable=False)
port = Column(Integer,default=) # 创建表结构方法
Base.metadata.create_all(engine) # 通过引擎engine,SqlORM基类 调用metadata中的create_all方法,这样远程数据库中如果存在子类中的表则不做动作,如果不存在则添加.如果存表名但是字段不一样也不做操作. if __name__ == '__main__':
SessionCls = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例,也就意味着一切连接都就绪了,就查你点连接了
session = SessionCls() # 实例化一个连接huihua
'''
# 增加纪录
h1 = Host(hostname='localhost',ip_addr='127.0.0.1') # 使用前面定义好SqlORM类Host,实例化一个对象,此对象包含了转换原生sql语句的规范.
h2 = Host(hostname='ubuntu',ip_addr='10.0.0.1',port=)
h3 = Host(hostname='ubuntu2',ip_addr='192.168.2.244',port=)
session.add(h3) # 可以一条一条添加
session.add_all([h1,h2]) # 也可以一次添加多条
#h2.hostname = 'ubuntu_test' # 只要没提交,此时修改也没问题
#session.rollback() # 撤销
session.commit() # 最后要提交.
''' '''
# 更改纪录 (更改纪录首先要查询到这条纪录,然后在进行更改)
res = session.query(Host).filter(Host.id == ).first() # 调用session.query(查哪个sqlORM类).fitler(查询条件).first(取几行),res为返回的是一条纪录
# res = session.query(Host).filter(Host.hostname == 'ubuntu' ).first() # 调用session.query(查哪个sqlORM类).fitler(查询条件).all()取所有
# res = session.query(Host.hostname,Host.id).filter(Host.hostname == 'ubuntu' ).first() # 查询指定字段
print("++>",res,res.hostname)
res.hostname = 'test server' # 直接更改,
session.commit() # 然后提交
''' # 删除操作(删除纪录,先获取对象,然后在删除)
res = session.query(Host).filter(Host.hostname.like('%ubuntu%')).all() # 调用session.query获取纪录对象结果集
print("------------>",res[].hostname,res[].hostname) session.delete(res[])
# print("------------>22",res[].hostname,res[].hostname)
# session.commit()

sqlalchemy简单例子

SqlAlchemy完整的例子(一对多外键联接1)_用法终极状态
  1.首先1对多外联,必须创建外键
#!/usr/bin/env python3.
#__author__:ted.zhou
import pymysql
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base # 注意返回的是个类,不是实例.
from sqlalchemy import Column,Integer,String,ForeignKey
from sqlalchemy.orm import sessionmaker # 导入sessionmaker模块,它自己是一个类,实例化它返回的还是一个类(是一个包含了数据库API信息和连接地址端口以及用户名和密码信息的类)不是一个实例
from sqlalchemy.orm import relationship Base = declarative_base() #生成一个SqlORM基类,接下来所有要创建的SqlORM的子类(理解成如果想用sqlalchemy来操作数据库中的表,就需要把数据库的表结构映射成SqlORM类) # 实例化引擎,只是把连接信息作为参数传入,并未真的连接.
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3307/test",echo=True) # echo=True可以显示转化后的原生SQL语句执行过程 class Host(Base): # 定义一个SqlORM类,继承Base类这样他就默认绑定了matedata和数据结构
__tablename__ = 'hosts' # 声明表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False) # 声明字段id,类型为int,为主键,自增长属性为真
hostname = Column(String(),unique=True,nullable=False) # 声明字段hostname,类型为String,是否唯一限制为True,是否可为空False
ip_addr = Column(String(),unique=True,nullable=False)
port = Column(Integer,default=)
groupid = Column(Integer,ForeignKey('group.id')) # 添加一个字段,并设置此字段类型为外键.
# 使用ForeignKey设置外键时注意亮点:
# 1. ForeignKey需要从SqlAlchemy中导入 from sqlalchemy import ForeignKey
# 2. ForeignKey(参数),参数是实实在在的表名,而不是封装了的SqlAlchemy 的ORM类名
'''
执行时原生语句的内容如下:
CREATE TABLE hosts (
id INTEGER NOT NULL AUTO_INCREMENT,
hostname VARCHAR() NOT NULL,
ip_addr VARCHAR() NOT NULL,
port INTEGER,
groupid INTEGER,
PRIMARY KEY (id),
UNIQUE (hostname),
UNIQUE (ip_addr),
FOREIGN KEY(groupid) REFERENCES `group` (id) # 这里就是设置外键的语句,可以参考记住
)
'''
class Group(Base):
__tablename__ = 'group' # 定义表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False)
groupname = Column(String(),unique=True,nullable=False) Base.metadata.create_all(engine) # 通过引擎engine,SqlORM基类 调用metadata中的create_all方法,这样远程数据库中如果存在子类中的表则不做动作,如果不存在则添加.如果存表名但是字段不一样也不做操作. if __name__ == '__main__':
SessionCls = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例,也就意味着一切连接都就绪了,就查你点连接了
session = SessionCls() # 实例化一个连接huihua
'''
# 先创建一个组
g1 = Group(groupname='g1')
g2 = Group(groupname='g2')
g3 = Group(groupname='g3')
session.add_all([g1,g2,g3])
# 创建
h1 = Host(hostname='linux1',ip_addr='10.0.0.1',port='',groupid=g1.id)
h2 = Host(hostname='ubuntu1',ip_addr='10.0.0.2',port='')
session.add_all([h1,h2])
session.commit() 我们在这一连串的代码中实现了,添加组,然后创建主机,设置h1的groupid = g1.id
但是结果是 h1的groupid最终加到数据库中的值为NULL,为什么?
原因是 你虽然在映射后的sqlalchemy的orm类实例化了g1,但是在数据库表中没有,并且你在实例化g1时,没有直接指定g1.id值,所以接下来h1实例化的时候取不到g1.id的值
那么问题来了,如果我在实例化g1的时候指定了id的值能不能成功呢.当然实际应用中自增长字段是 不会自己指定值的,但这里测试.我猜测是可以的.下面我们做这个测试. ''' '''
# 测试
g4 = Group(id=,groupname='g4')
h3 = Host(hostname='ubuntu2',ip_addr='10.0.0.3',port=)
h4 = Host(hostname='linux2',ip_addr='10.0.0.4',port=,groupid=g4.id)
session.add_all([g4,h3,h4])
session.commit()
# 执行结果:
# mysql> select * from hosts;
# +----+----------+----------+------+---------+
# | id | hostname | ip_addr | port | groupid |
# +----+----------+----------+------+---------+
# | | linux1 | 10.0.0.1 | | NULL |
# | | ubuntu1 | 10.0.0.2 | | NULL |
# | | ubuntu2 | 10.0.0.3 | | NULL |
# | | linux2 | 10.0.0.4 | | |
# +----+----------+----------+------+---------+
# rows in set (0.00 sec)
# 所以上面上面的判断是正确的
'''

  上面的例子就是在Host中添加了一个groupid外键到Group.id。

    '''
接下来,我想知道id=4的host所属组的组名,怎么获取?
  h = session.query(Host).filter(Host.id == ).first()
  print('+++++++++++++++>',h.groupname) # 打印h.groupname
  # 结果: AttributeError: 'Host' object has no attribute 'groupname'
说明直接调用是不行的,那么怎样才能获得groupname呢?
答案:要用到关联查询了,要导入relationship不是relationships,也就是说你希望在Host类里,通过什么字段就可以掉用到groupname,
于是在class Host类中加入: group = relationship('Group')这里的参数是类,而不是表名.说明通过反射的方法,把Group实例嵌到Host实例中的group字段中.这个时候就可以使用group.groupname获得名称了.

  代码改成如下:

  SqlAlchemy完整的例子(一对多外键联接)2_用法终极状态:

 #!/usr/bin/env python3.
#__author__:ted.zhou
import pymysql
from sqlalchemy import create_engine # 导入引擎类
from sqlalchemy.ext.declarative import declarative_base # 导入sqlalchemy的一个扩展模块declarative_base,此模块调用返回一个封装好的 metadata元数据和表名以及表字段 的类.注意返回的是个类,不是实例.
from sqlalchemy import Column,Integer,String,ForeignKey # 导入和创建表结构相关的模块
from sqlalchemy.orm import sessionmaker # 导入sessionmaker模块,它自己是一个类,实例化它返回的还是一个类(是一个包含了数据库API信息和连接地址端口以及用户名和密码信息的类)不是一个实例
# 这句话的意思,拿到数据库API(传入的bind=engine参数作中记录了数据库的API和连接信息),创建一个连接的类.这个类里有连接信息,和数据库API信息,接下来要创建一个连接session就要实例化这个类
from sqlalchemy.orm import relationship # 导入ralationship模块 Base = declarative_base() #生成一个SqlORM基类,接下来所有要创建的SqlORM的子类(理解成如果想用sqlalchemy来操作数据库中的表,就需要把数据库的表结构映射成SqlORM类) # 实例化引擎,只是把连接信息作为参数传入,并未真的连接.
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3307/test",echo=True) # echo=True可以显示转化后的原生SQL语句执行过程 class Host(Base): # 定义一个SqlORM类,继承Base类这样他就默认绑定了matedata和数据结构
__tablename__ = 'hosts' # 声明表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False) # 声明字段id,类型为int,为主键,自增长属性为真
hostname = Column(String(),unique=True,nullable=False) # 声明字段hostname,类型为String,是否唯一限制为True,是否可为空False
ip_addr = Column(String(),unique=True,nullable=False)
port = Column(Integer,default=)
groupid = Column(Integer,ForeignKey('group.id')) # 添加一个字段,并设置此字段类型为外键.
group = relationship('Group') # 建立关联关系 class Group(Base):
__tablename__ = 'group' # 定义表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False)
groupname = Column(String(),unique=True,nullable=False) # 创建表结构方法
Base.metadata.create_all(engine) # 通过引擎engine,SqlORM基类 调用metadata中的create_all方法,这样远程数据库中如果存在子类中的表则不做动作,如果不存在则添加.如果存表名但是字段不一样也不做操作. if __name__ == '__main__':
SessionCls = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例,也就意味着一切连接都就绪了,就查你点连接了
session = SessionCls() # 实例化一个连接huihua
'''
再次测试!!!
'''
h = session.query(Host).filter(Host.id == ).first()
print('+++++++++++++++>',h.group.groupname) # 打印h.group.groupname
# 执行结果: +++++++++++++++> g4
        总结:要用到关联查询,两部:1.导入sqlalchemy.orm模块中的relationship 2.使用relationship建立关联关系.

刚刚我们实现了一对多,一个主机对应一个组,并且通过ralationship()建立关系后,使用host.group.groupname获得组名。

那么问题来了,我们如何实现通过组,获得组中包含多少个主机呢?
答案:前面我们只是在Host 类中声明了relationship(),所以通过host.group.groupname能过获得groupname的信息,
所以如果我们想通过group.hosts获得主机的话,就需要在relationship()中声明和Host的关系。
于是代码改成如下:
SqlAlchemy例子(一对多外键联接3)_通过组获取主机_双方声明关系
 #!/usr/bin/env python3.
#__author__:ted.zhou
import pymysql
from sqlalchemy import create_engine # 导入引擎类
from sqlalchemy.ext.declarative import declarative_base # 导入sqlalchemy的一个扩展模块declarative_base,此模块调用返回一个封装好的 metadata元数据和表名以及表字段 的类.注意返回的是个类,不是实例.
from sqlalchemy import Column,Integer,String,ForeignKey # 导入和创建表结构相关的模块
from sqlalchemy.orm import sessionmaker # 导入sessionmaker模块,它自己是一个类,实例化它返回的还是一个类(是一个包含了数据库API信息和连接地址端口以及用户名和密码信息的类)不是一个实例
# 这句话的意思,拿到数据库API(传入的bind=engine参数作中记录了数据库的API和连接信息),创建一个连接的类.这个类里有连接信息,和数据库API信息,接下来要创建一个连接session就要实例化这个类
from sqlalchemy.orm import relationship # 导入ralationship模块 Base = declarative_base() #生成一个SqlORM基类,接下来所有要创建的SqlORM的子类(理解成如果想用sqlalchemy来操作数据库中的表,就需要把数据库的表结构映射成SqlORM类) # 实例化引擎,只是把连接信息作为参数传入,并未真的连接.
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3307/test",echo=True) # echo=True可以显示转化后的原生SQL语句执行过程 class Host(Base): # 定义一个SqlORM类,继承Base类这样他就默认绑定了matedata和数据结构
__tablename__ = 'hosts' # 声明表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False) # 声明字段id,类型为int,为主键,自增长属性为真
hostname = Column(String(),unique=True,nullable=False) # 声明字段hostname,类型为String,是否唯一限制为True,是否可为空False
ip_addr = Column(String(),unique=True,nullable=False)
port = Column(Integer,default=)
groupid = Column(Integer,ForeignKey('group.id')) # 添加一个字段,并设置此字段类型为外键.
group = relationship('Group') # 建立关联关系 class Group(Base):
__tablename__ = 'group' # 定义表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False)
groupname = Column(String(),unique=True,nullable=False)
hosts = relationship('Host') # 在组类中声明和Host类的关联 # 创建表结构方法
Base.metadata.create_all(engine) # 通过引擎engine,SqlORM基类 调用metadata中的create_all方法,这样远程数据库中如果存在子类中的表则不做动作,如果不存在则添加.如果存表名但是字段不一样也不做操作. if __name__ == '__main__':
SessionCls = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例,也就意味着一切连接都就绪了,就查你点连接了
session = SessionCls() # 实例化一个连接huihua
'''
# 我们先测试
g4 = session.query(Group).filter(Group.id == ).all()
print("+++++++++>",g4.host)
#结果不行,因为Group中没有host字段
# 是不是应该在Group类中同样要通过relationship('Host') 绑定关系,在Group类中添加语句如下: hosts = relationship('Host')
''' '''
# 接着测试:
g4 = session.query(Group).filter(Group.id == ).first() # 这里要用first(),不能用all()否则得到的是一个列表
print("+++++++++>",g4.hosts)
# 结果:+++++++++> [<__main__.Host object at 0x103843048>] ,如果有多个,那么得到的是两个obj对象 '''
反向就查出来了,是不是很方便,能够这么使用的原因:1.Host中的groupid和Group中的id外键关联,如果没有关联关系肯定不行
2. Group类中也要调用relationship('Host')进行关联
那么问题来了,一个父亲,要和多个儿子做ralationship()方法的关联,这代码看上去是不是很麻烦.
sqlalchemy语法也考虑到了,只需要在儿子类中把relationship()语法写成: hosts = relationship('Host',backref='hosts')
于是代码改成如下:
SqlAlchemy例子(一对多外键联接4)_通过组获取主机_一方声明双方起作用
 #!/usr/bin/env python3.
#__author__:ted.zhou
import pymysql
from sqlalchemy import create_engine # 导入引擎类
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,ForeignKey # 导入和创建表结构相关的模块
from sqlalchemy.orm import sessionmaker # 导入sessionmaker模块,它自己是一个类,实例化它返回的还是一个类 from sqlalchemy.orm import relationship # 导入ralationship模块 Base = declarative_base() # 实例化引擎,只是把连接信息作为参数传入,并未真的连接.
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3307/test",echo=True) # echo=True可以显示转化后的原生SQL语句执行过程 class Host(Base): # 定义一个SqlORM类,继承Base类这样他就默认绑定了matedata和数据结构
__tablename__ = 'hosts' # 声明表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False) # 声明字段id,类型为int,为主键,自增长属性为真
hostname = Column(String(),unique=True,nullable=False) # 声明字段hostname,类型为String,是否唯一限制为True,是否可为空False
ip_addr = Column(String(),unique=True,nullable=False)
port = Column(Integer,default=)
groupid = Column(Integer,ForeignKey('group.id')) # 添加一个字段,并设置此字段类型为外键.
group = relationship('Group',backref='hosts') # 建立关联关系,这一句很关键,一句代码就实现了双向关系的声明 class Group(Base):
__tablename__ = 'group' # 定义表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False)
groupname = Column(String(),unique=True,nullable=False)
# hosts = relationship('Host') # 这里就不需要用了 # 创建表结构方法
Base.metadata.create_all(engine) # 通过引擎engine,SqlORM基类 调用metadata中的create_all方法,这样远程数据库中如果存在子类中的表则不做动作,如果不存在则添加.如果存表名但是字段不一样也不做操作. if __name__ == '__main__':
SessionCls = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例,也就意味着一切连接都就绪了,就查你点连接了
session = SessionCls() # 实例化一个连接huihua # 接着测试:
g4 = session.query(Group).filter(Group.id == ).first() # 这里要用first(),不能用all()否则得到的是一个列表
print("+++++++++>",g4.hosts)
# 结果:+++++++++> [<__main__.Host object at 0x103843048>] ,如果有多个,那么得到的是两个obj对象
  总结:用group = relationship('Group',backref='hosts') # 可以建立双向关系
同时还有一个很类似backref 的用法,就是relationship('Group',back_populates='hosts')
那么我们会问为什会有一个累死backref的功能呢,它用在什么时候.一点区别没有吗.
区别是: 用法上不一样relationship('Group',back_populates='hosts')必须是成对出现的,
也就是说在儿子处group = relationship('Group',back_populates='hosts'),在父亲处就必须有 hosts = relationship('Host',back_populates='group')
那么我们猜想应用场景也就是做统一管理接口的时候,就是在父亲处统一管理,让儿子可不可以外链它.增加了安全性。
前面一对多外联的基本用法演示完成,我们知道实际开发中有很多使用join的方法进行外联查询
SqlAlchemy例子(一对多外键联接5)_innerjoin_leftjoin_rightjoin
 #!/usr/bin/env python3.
#__author__:ted.zhou
import pymysql
from sqlalchemy import create_engine # 导入引擎类
from sqlalchemy.ext.declarative import declarative_base # 导入sqlalchemy的一个扩展模块declarative_base,此模块调用返回一个封装好的 metadata元数据和表名以及表字段 的类.注意返回的是个类,不是实例.
from sqlalchemy import Column,Integer,String,ForeignKey,func # 导入和创建表结构相关的模块
from sqlalchemy.orm import sessionmaker # 导入sessionmaker模块,它自己是一个类,实例化它返回的还是一个类(是一个包含了数据库API信息和连接地址端口以及用户名和密码信息的类)不是一个实例
# 这句话的意思,拿到数据库API(传入的bind=engine参数作中记录了数据库的API和连接信息),创建一个连接的类.这个类里有连接信息,和数据库API信息,接下来要创建一个连接session就要实例化这个类
from sqlalchemy.orm import relationship # 导入ralationship模块 Base = declarative_base() #生成一个SqlORM基类,接下来所有要创建的SqlORM的子类(理解成如果想用sqlalchemy来操作数据库中的表,就需要把数据库的表结构映射成SqlORM类) # 实例化引擎,只是把连接信息作为参数传入,并未真的连接.
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3307/test",echo=True) # echo=True可以显示转化后的原生SQL语句执行过程 class Host(Base): # 定义一个SqlORM类,继承Base类这样他就默认绑定了matedata和数据结构
__tablename__ = 'hosts' # 声明表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False) # 声明字段id,类型为int,为主键,自增长属性为真
hostname = Column(String(),unique=True,nullable=False) # 声明字段hostname,类型为String,是否唯一限制为True,是否可为空False
ip_addr = Column(String(),unique=True,nullable=False)
port = Column(Integer,default=)
groupid = Column(Integer,ForeignKey('group.id')) # 添加一个字段,并设置此字段类型为外键.
group = relationship('Group',backref='hosts') # 建立关联关系 class Group(Base):
__tablename__ = 'group' # 定义表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False)
groupname = Column(String(),unique=True,nullable=False)
# hosts = relationship('Host') # 这里就不需要用了 class test_table(Base):
__tablename__ = 'test_table'
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False)
name2 = Column(String(),unique=True,nullable=False) # 创建表结构方法
Base.metadata.create_all(engine) # 通过引擎engine,SqlORM基类 调用metadata中的create_all方法,这样远程数据库中如果存在子类中的表则不做动作,如果不存在则添加.如果存表名但是字段不一样也不做操作. if __name__ == '__main__':
SessionCls = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例,也就意味着一切连接都就绪了,就查你点连接了
session = SessionCls() # 实例化一个连接huihua
'''
# inner join
obj = session.query(Host).join(Host.group).filter().all()
print('+++++++++>',obj)
# 执行时,调用的原生SQL语句是:SELECT hosts.id AS hosts_id, hosts.hostname AS hosts_hostname, hosts.ip_addr AS hosts_ip_addr, hosts.port AS hosts_port, hosts.groupid AS hosts_groupid FROM hosts INNER JOIN `group` ON `group`.id = hosts.groupid
# 分析原生sql,得出结论:join(Host.group)这段代码,首先说明1. Host 中有group字段,并且group字段是通过relationship()做关联的,那通过什么关联的呢 继而得出条件2.Host 和Group有外键 # 上面得到的也只有一张表的数据,那如果想得到两张表的数据呢
obj2 = session.query(Host,Group).join(Host.group).filter().all()
print("obj2:",obj2)
# 解析成原生sql为:
# SELECT hosts.id AS hosts_id, hosts.hostname AS hosts_hostname, hosts.ip_addr AS hosts_ip_addr, hosts.port AS hosts_port, hosts.groupid AS hosts_groupid, `group`.id AS group_id, `group`.groupname AS group_groupname FROM hosts INNER JOIN `group` ON `group`.id = hosts.groupid
'''
'''
# 上面两个都是有建立过外键的情况下进行查询,假如没有创建过字段为外键的情况下能查询呢
obj3 = session.query(Host,Group).join(Host.groupid==Group.id).filter().all()
print("obj3:",obj3)
# 经测试,行不通,难道说join查询在sqlalchemy中只支持带外键的查询吗.未知???这将对我了解数据库有很大帮助
''' # 使用group_by 对查询结果进行分类聚合
obj4 = session.query(func.count(Host,Group)).join(Group).filter().group_by(Group.groupname).first()
print('obj4:',obj4)
'''
# 下面我们测试下当没有外键关系的表,外链查询的结果
obj5 = session.query(Host,test_table).join(test_table).filter().all()
print('obj5:',obj5)
# 结果报错:sqlalchemy.exc.NoForeignKeysError: Can't find any foreign key relationships between 'hosts' and 'test_table'.
# 说明要执行join查询需要有外键关系.
# 但是原生的sql是可以查询没有外键关系的两种表的
# SELECT hosts.id AS hosts_id, hosts.hostname AS hosts_hostname, hosts.ip_addr AS hosts_ip_addr, hosts.port AS hosts_port, hosts.groupid AS hosts_groupid FROM hosts INNER JOIN `test_table` ON `test_table`.id = hosts.groupid;
# 结果:Empty set (0.00 sec)
# 那么接下来又一个问题要解决,就是在sqlalchemy中如何实现没有外键关系进行 join查询???
'''

1对多外联查询演示

前面SqlAlchemy完整的例子(一对多外键联接1-5) 这些都是一对多的外链,从基础到高级用法.
但实际开发中,经常有多对多的场景,比如一个主机属于多个组.前面1-5个例子都无法实现,因为每一个主机一条纪录,主机名是唯一的,你没有办法为同一个主机名创建2条纪录,而只是主机组id不一样.
即使可以,也不符合我们作为技术的宗旨,同一样的纪录最好只需要录入一遍.所以如果想实现一个主机属于多个组,就应该单独创建一张主机——组的关系表.表中只纪录主机id和组id.并且不论你用不用orm所有数据库表结构的many to many的关系,也都是通过关系表实现
在原生sql中,拿mysql来说,看起来是没有什么难度的.
假设我们现在创建了一个表:
表名:HostToGroup
id host_id group_id
1 1 1
2 1 2
3 2 1
那么我们想通过关系表查找 主机名,组名,是不是每次查都需要各种来回的join查询.
而orm的存在简化这种操作.实现了不用调用中间表,通过
Host.groups()就可以查出这个主机所属的组的列表
group.hosts() 就可以查出这个组中包含的所有主机的列表.
具体内部代码如何实现的,我们不需要知道,只要知道如何使用sqlalchemy代码实现就可以了.
代码范例:
SqlAlchemy例子(对对多外键联接1)_对原生sql优化的内容
 #!/usr/bin/env python3.
#__author__:ted.zhou
import pymysql
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,ForeignKey,func # 导入和创建表结构相关的模块
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import relationship # 导入ralationship模块
from sqlalchemy import Table # 要先导入Table,接下来我们使用Table来创建关系表,而不是使用类的形势创建关系表 Base = declarative_base() #生成一个SqlORM基类 Host2Group = Table('host_2_group',Base.metadata, # 这里为什么用Table方式创建表,而不使用class方式,首先我们要知道Table方式创建的表返回的是一个实例,我们可以通过实例.insert()插入数据.而class插入数据的时候却要先实例化.所以我们这里是要用到它返回实例可以操作的特性,用到Table,而不用class
Column('host_id',ForeignKey('hosts.id'),primary_key=True), # 这里我们看这个表中有两个主键,为什么呢
Column('group_id',ForeignKey('group.id'),primary_key=True), # 因为确保 (主机id-组id) 唯一,且他们两个都不能为空
)
'''
20 这里表创建好了,并且使用的是Table,
21 我们说了sqlalchemy优化了这种many to many的关系实现方式.目前知道能简化的方式:
22 1.不用通过join调用,直接通过Host.groups()获得某个主机所属的组,直接通过group.hosts()获得某个组中的主机
23 那我现在告诉你第二个优化的点
24 2.在新建一个主机 并且关联到某一个组时,自动的往关系表中添加一条host_id和group_id的纪录.(是不是很高级~自动添加,不用像原生SQL一样,要多写一条sql语句)
25 这也是前面使用Table创建这个关系表的原因
26 紧接着你会问怎么实现呢? 別着急,很简单,还记得我们使用relationship()方法,来指定hosts表和group表的关联关系吗?
27 我们只需要在原有relationship()方法中,加secondary=Host2Group,并且把之前创建的外键字段删除
28 最终应该是
29 groups = relationship('Group',secondary=Host2Group,backref='hosts')
''' # 实例化引擎,只是把连接信息作为参数传入,并未真的连接.
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3307/test",echo=True) # echo=True可以显示转化后的原生SQL语句执行过程 class Host(Base): # 定义一个SqlORM类,继承Base类这样他就默认绑定了matedata和数据结构
__tablename__ = 'hosts' # 声明表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False) # 声明字段id,类型为int,为主键,自增长属性为真
hostname = Column(String(),unique=True,nullable=False) # 声明字段hostname,类型为String,是否唯一限制为True,是否可为空False
ip_addr = Column(String(),unique=True,nullable=False)
port = Column(Integer,default=)
# groupid = Column(Integer,ForeignKey('group.id')) # 此时要删除这个外键了
# group = relationship('Group',backref='hosts') # 这个关系也要改了
groups = relationship('Group',
secondary=Host2Group, # 指定中间表的实例
backref='hosts') # 最终改成这个样子了 '''
# 因为关系表两个外键一个host_id,外键的是hosts.id
# 另外一个外溅group_id,外键的是group.id
# 就是根据这两个外键,并且通过relationship()方法才做了优化 many to many关系的操作语法.
''' class Group(Base):
__tablename__ = 'group' # 定义表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False)
groupname = Column(String(),unique=True,nullable=False)
# hosts = relationship('Host') # 这里就不需要用了 # 创建表结构方法
Base.metadata.create_all(engine) if __name__ == '__main__':
SessionCls = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例,也就意味着一切连接都就绪了,就查你点连接了
session = SessionCls() # 实例化一个连接huihua '''
一 首先我们先创建主机和组
# 创建3个组
# g1 = Group(groupname='g1',id=)
# g2 = Group(groupname='g2',id=)
# g3 = Group(groupname='g3') # 创建一个主机
# h1 = Host(hostname='linux1',ip_addr='10.0.0.1',port=) #
# session.add_all([g1,g2,g3,h1])
# session.commit()
'''
'''
二. 然后我们将 主机和组关联起来
groups = session.query(Group).filter().all() # 查出所有组
h = session.query(Host).filter(Host.hostname == 'linux1').first() # 查出一个主机
h.groups = groups # 将这个主机的groups 直接赋值 上面所查到的groups
session.commit() # 提交后,就会在关系表中host_2_group 自动创建3条纪录,前提就是1.relationship()的设置,和2.关系表外键的设置
''' '''
# 三 .接下来我们来试试查询
# 查看主机所属的所有组
h = session.query(Host).filter(Host.hostname=='linux1').first()
print('++++++++++++>>>>>',h.groups)
# 执行结果:
# ++++++++++++>>>>> [<__main__.Group object at 0x103717748>, <__main__.Group object at 0x1037177b8>, <__main__.Group object at 0x103717828>]
# 我们看到有3个组的对象
# 查看组里所有的主机
g = session.query(Group).filter(Group.groupname == 'g2').first()
print('----------->>>>>>',g.hosts)
# 执行结果:
# ----------->>>>>> [<__main__.Host object at 0x10383d320>]
# 我们看到有一个主机对象.
      总结:sqlalchemy是多么的神奇.好的很
前面查询的host.groups 和 group.hosts的结果都是对象类型,那么我们最终要打印的肯定不是对象,而是字符串.
问题:怎样将结果打印成字符串呢. sqlalchemy语法本身是没有方法的,我们看我们是通过class创建的orm类,那么我们可以定义__repr__()方法,来随意指定返回的内容
因此 我们在创建 Host和Group类中定义 def __repr__(self):
于是代码改成如下:
SqlAlchemy例子(对对多外键联接2)_将返回的结果转换成字符串
 #!/usr/bin/env python3.
#__author__:ted.zhou
import pymysql
from sqlalchemy import create_engine # 导入引擎类
from sqlalchemy.ext.declarative import declarative_base # 导入sqlalchemy的一个扩展模块declarative_base,此模块调用返回一个封装好的 metadata元数据和表名以及表字段 的类.注意返回的是个类,不是实例.
from sqlalchemy import Column,Integer,String,ForeignKey,func # 导入和创建表结构相关的模块
from sqlalchemy.orm import sessionmaker # 导入sessionmaker模块,它自己是一个类,实例化它返回的还是一个类(是一个包含了数据库API信息和连接地址端口以及用户名和密码信息的类)不是一个实例
# 这句话的意思,拿到数据库API(传入的bind=engine参数作中记录了数据库的API和连接信息),创建一个连接的类.这个类里有连接信息,和数据库API信息,接下来要创建一个连接session就要实例化这个类
from sqlalchemy.orm import relationship # 导入ralationship模块 from sqlalchemy import Table # 要先导入Table,接下来我们使用Table来创建关系表,而不是使用类的形势创建关系表 Base = declarative_base() #生成一个SqlORM基类,接下来所有要创建的SqlORM的子类(理解成如果想用sqlalchemy来操作数据库中的表,就需要把数据库的表结构映射成SqlORM类) Host2Group = Table('host_2_group',Base.metadata, # 这里为什么用Table方式创建表,而不使用class方式,首先我们要知道Table方式创建的表返回的是一个实例,我们可以通过实例.insert()插入数据.而class插入数据的时候却要先实例化.所以我们这里是要用到它返回实例可以操作的特性,用到Table,而不用class
Column('host_id',ForeignKey('hosts.id'),primary_key=True), # 这里我们看这个表中有两个主键,为什么呢
Column('group_id',ForeignKey('group.id'),primary_key=True), # 因为确保 (主机id-组id) 唯一,且他们两个都不能为空
) # 实例化引擎,只是把连接信息作为参数传入,并未真的连接.
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3307/test",echo=True) # echo=True可以显示转化后的原生SQL语句执行过程 class Host(Base): # 定义一个SqlORM类,继承Base类这样他就默认绑定了matedata和数据结构
__tablename__ = 'hosts' # 声明表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False) # 声明字段id,类型为int,为主键,自增长属性为真
hostname = Column(String(),unique=True,nullable=False) # 声明字段hostname,类型为String,是否唯一限制为True,是否可为空False
ip_addr = Column(String(),unique=True,nullable=False)
port = Column(Integer,default=)
groups = relationship('Group',secondary=Host2Group,backref='hosts') # 最终改成这个样子了 def __repr__(self): # 定义__repr__方法,默认返回字符串
return "<id=%s,hostname=%s,ip_addr=%s>"%(self.id,
self.hostname,
self.ip_addr) class Group(Base):
__tablename__ = 'group' # 定义表名
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False)
groupname = Column(String(),unique=True,nullable=False) def __repr__(self): # 定义__repr__方法,默认返回字符串
return "<id=%s,name=%s>"%(self.id,self.groupname)
# 创建表结构方法
Base.metadata.create_all(engine) # 通过引擎engine,SqlORM基类 调用metadata中的create_all方法,这样远程数据库中如果存在子类中的表则不做动作,如果不存在则添加.如果存表名但是字段不一样也不做操作. if __name__ == '__main__':
SessionCls = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例,也就意味着一切连接都就绪了,就查你点连接了
session = SessionCls() # 实例化一个连接huihua # 查看主机所属的所有组
h = session.query(Host).filter(Host.hostname=='linux1').first()
print('++++++++++++>>>>>',h.groups) # 打印结果:
# ++++++++++++>>>>> [<id=,name=g1>, <id=,name=g2>, <id=,name=g3>] g = session.query(Group).filter(Group.groupname == 'g2').first()
print('----------->>>>>>',g.hosts)
# 打印结果
# ----------->>>>>> [<id=,hostname=linux1,ip_addr=10.0.0.1>]
请仔细查看上面两个范例代码,保证能看到你想看到的东西
至此,sqlalchemy的一些简单用法,外键用法,join用法,以及多对多关系的用法这节课就讲完了。基本上能够满足70%了,其他的实际需求要自己查。




												

python2.0_s12_day11_SqlAlchemy使用介绍的更多相关文章

  1. Python第一部分--Python简介+第一个程序+Python2和Python3介绍 001-016

    一.Python起源 1.1 解释器(科普) 1.2Python的设计目标 1.3 Python的设计哲学 02.为什么学Python? 代码量少 同一样问题,不用的语言解决,代码量差距还是很多的,一 ...

  2. python2.0_s12_day10_rabbitMQ使用介绍

    RabbitMQ RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列(M ...

  3. Openstack Swift中间件编写

    关于openstack swift的资料可以看这里,这里还有这里. 准备环境 从零开始接触的同学可以先从swift的all in one部署开始学习,在本机搭建好swift环境就可以进行简单的测试了. ...

  4. python2.0_day16_django_url_view_models_template介绍

    本节内容 Django流程介绍 Django url Django view Django models Django template Django form Django admin Django ...

  5. [Python2]介绍关于Uiautomator的watcher使用场景及使用方法

    [官方的介绍]: Watcher You can register watcher to perform some actions when a selector can not find a mat ...

  6. Python3基础(1)Python介绍、Python2 与Python3、变量、用户输入、if...else和for循环、while循环、break与continue

    ---------------个人学习笔记--------------- ----------------本文作者吴疆-------------- ------点击此处链接至博客园原文------ P ...

  7. Python基础教程(016)--Python2和Python3的介绍

    前言 Python2和Python3的区别 内容 Python3是现在和未来的主要版本 Python3没有考虑向下兼容. 官方提供了一个Python过度版本Python2.6 Python2.6及支持 ...

  8. python2.7到python3代码转换脚本2to3的一些介绍

       你的位置: Home ‣ Dive Into Python 3 ‣ 难度等级: ♦♦♦♦♦   使用2to3将代码移植到Python 3 ❝ Life is pleasant. Death is ...

  9. <转>Python3.x和Python2.x的区别介绍

    1.性能Py3.0运行 pystone benchmark的速度比Py2.5慢30%.Guido认为Py3.0有极大的优化空间,在字符串和整形操作上可以取得很好的优化结果.Py3.1性能比Py2.5慢 ...

随机推荐

  1. Oracle_字符集问题(数据库与客户端字符集关联关系)

    http://blog.163.com/jiankun_liu/blog/static/1863927762013698175289 ********************************* ...

  2. LeetCode: Maximal Rectangle 解题报告

    Maximal RectangleGiven a 2D binary matrix filled with 0's and 1's, find the largest rectangle contai ...

  3. FreeRTOS 低功耗之睡眠模式

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 低功耗是 MCU 的一项重要的指标,比如某些可穿戴的设备,其携带的电量有限,如果整个电路消耗的电量特别大的话 ...

  4. JAVA-MyEclipse第一个实例

    相关资料: <21天学通Java Web开发> 实例代码: MyEclipse第一个实例1.打开MyEclipse程序.2.在PacKage视图->右击->New|Web Pr ...

  5. PS_图象调整_太暗/过亮_曝光不足/过度

    对于曝光不足,图像太暗. 1.调整[色阶] 图象>调整>色阶   clrl+L 然后拖动"黑","灰","白"三个滑块. 2.使 ...

  6. linux内核支持U-disk和U转串

    配置内核 make menuconfig,选中device驱动 Device Drivers ---->USB support--->USB Serial Converter suppor ...

  7. 信号值大于-75dBm时

    dBm是一个表示功率绝对值的值,是以1mw为0dbm,公式dbm=10×lg(毫瓦数/1).所以,为负值 这个值越大,表示信号越好,如-70dbm信号比-90dbm好  信号值大于-75dBm时,说明 ...

  8. 推断iframe里的页面载入完毕

    //推断iframe是否载入完毕,RMid为iframe的ID document.getElementById("RMid").onload = function () { ale ...

  9. mac配置完ssh依然提示"Enter passphrase for key"解决方法

    使用Git,每次都提示输入命令. 这个问题折磨很久,明明已经配置过ssh了,可是每次还要提示输入密码,从网上查查,最后一条命令解决问题: 问题提示: Enter passphrase for key ...

  10. windows 解压缩命令

    首先安装winrar 压缩: 命令:start winrar a test test.py 解压: 命令:start winrar x -y test.rar F:\batShell\test\tes ...