SQLAlchemy

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

虽然小弟是个小菜鸟,虽然小弟对数据库没有见多识广,但说内心话当我看到SQLAlchemy这个架构设计时,真的有一种神奇的感受。简洁明了,逻辑清晰。原谅小弟lowB的心态。最关键的是不须要再研究那些复杂繁琐的数据库操做细节了。mysql

使用SQLAlchemy操做数据库的方式方法有不少种,如经过执行原生SQL语句操做,经过对象操做等。可是在这里只介绍一种最终执行结果的操做,而不是相似中间状态的一些操做。sql

 

1、基本操做

使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 全部组件对数据进行操做。根据类建立对象,对象转换成SQL,执行SQL。数据库

#!/usr/bin/env python
# _*_coding:utf-8 _*_

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine


Base = declarative_base()
engine = create_engine("mysql+mysqldb://root:123456@192.168.1.106:3306/test1", max_overflow=5, echo=True)    # echo控制是否显示操做过程


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)
    prot = Column(Integer, default=22)


# 寻找Base的全部子类,按照子类的结构在数据库中生成对应的数据表信息
Base.metadata.create_all(engine)  # 建立全部的表结构


if __name__ == '__main__':

    SessionCls = sessionmaker(bind=engine)   # 建立与数据库会话的session class,返回的是一个类,而不是一个实例
    session = SessionCls()    # 链接数据库的实例,就是用它来对数据库作实际的操做

# ###################### 增 #############################

    # 建立表中数据的实例
    # h1 = Host(hostname='localhost', ip_addr='127.0.0.1')
    # h2 = Host(hostname='centos', ip_addr='172.16.16.166')

    # session.add(h1)   # 单条建立
    # session.add_all([h1, h2])   # 批量建立
    # session.commit()    # 真正的提交数据库操做

# ###################### 查 ###########################

    # obj = session.query(Host).filter(Host.hostname == 'centos').all()
    # print obj
    # ret = session.query(User).filter_by(name='sb').first()

    # ret = session.query(User).filter_by(name='sb').all()

    # ret = session.query(User).filter(User.name.in_(['sb','bb'])).all()

    # ret = session.query(User.name.label('name_label')).all()
    # print ret,type(ret)

    # ret = session.query(User).order_by(User.id).all()

    # ret = session.query(User).order_by(User.id)[1:3]

    # session.commit()

# ###################### 删除 ###########################

    # obj = session.query(Host).filter(Host.hostname == 'centos').first()
    # session.delete(obj)
    #
    # session.commit()


# ###################### 更新 ###########################

    # obj = session.query(Host).filter_by(hostname='localhost').first()
    # obj.hostname = "chenchao"
    # print obj
    # session.commit()

 

更多功能参见文档,猛击这里下载PDF编程

 注意:SQLAlchemy不能修改已经存在的表的表结构。若是须要可使用SQLAlchemy开发者开源的另一个软件Alembic来完成。centos

 

2、一对多关联

因为SQLAlchemy不能对已经存在的表修改表结构,处于测试的缘由,咱们能够建立新的表。session

 一、建立表架构

#!/usr/bin/env python
# _*_coding:utf-8 _*_

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine


Base = declarative_base()
engine = create_engine("mysql+mysqldb://root:123456@192.168.1.106:3306/test1", max_overflow=5, echo=True)


class Host1(Base):   # 这个类就是一个表,这里只是映射成功了
    __tablename__ = 'hosts1'
    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)
    prot = Column(Integer, default=22)
    group_id = Column(Integer, ForeignKey('group1.id'))

class Group1(Base):
    __tablename__ = 'group1'
    id = Column(Integer, primary_key=True)
    groupname = Column(String(64), unique=True, nullable=False)


# 寻找Base的全部子类,按照子类的结构在数据库中生成对应的数据表信息
Base.metadata.create_all(engine)  # 建立全部的表结构

结果:框架

 

二、 建立数据:编程语言

if __name__ == '__main__': SessionCls = sessionmaker(bind=engine)   # 建立与数据库会话的session class,返回的是一个类,而不是一个实例
    session = SessionCls()    # 链接的实例
 g1 = Group1(groupname='g1') g2 = Group1(groupname='g2') g3 = Group1(groupname='g3') session.add_all([g1, g2, g3]) # 同时为host1建立两条数据,但外键的参数不一样。
    h1 = Host1(hostname='chenchao1', ip_addr='192.168.1.1',group_id=g1.id) h2 = Host1(hostname='chenchao2', ip_addr='192.168.1.2',group_id=2) session.add_all([h1, h2]) session.commit()
建立数据

 

用传入对象的方法和直接传id的方法分别建立两条外键的数据。

结果:

咱们发现当在建立数据的时候,传入对象并不能建立外键的值。由于当时的group表里面尚未数据。因此在插入外键数据时要确保对应的数据已经存在。

    SessionCls = sessionmaker(bind=engine)   # 建立与数据库会话的session class,返回的是一个类,而不是一个实例
    session = SessionCls()    # 链接的实例
 g3 = session.query(Group1).filter(Group1.groupname == 'g3').first() h3 = session.query(Host1).filter(Host1.hostname == 'chenchao1').update({'group_id': g3.id}) session.commit()
插入外键数据

 

 

三、查找外键数据

在host表里经过定义某个字段就能够调用这个字段来获取外键表中的某个数据。

注意:这里的方法是sqlalchemy来帮咱们实现的。并非要修改数据库中的表结构。

from sqlalchemy.orm import relationship   # 导入


class Host1(Base):   # 这个类就是一个表,这里只是映射成功了
    __tablename__ = 'hosts1'
    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)
    prot = Column(Integer, default=22)
    group_id = Column(Integer, ForeignKey('group1.id'))
    group = relationship('Group1')     #定义一个特殊的字段。括号里写的是一个类名,而不是表名

if __name__ == '__main__':
    SessionCls = sessionmaker(bind=engine)   
    session = SessionCls()    # 链接的实例
    h3 = session.query(Host1).filter(Host1.hostname == 'chenchao1').first()
    print h3.group.groupname    # 经过调用设置的字段就能够获取到外键表中的对应数据
    session.commit()

同理,若是要实现双向查询,那么把relationship()也添加到Group类里面,能够实现双向查询。可是,也能够只在Host表里作双向查询。

class Host1(Base):   # 这个类就是一个表,这里只是映射成功了
    __tablename__ = 'hosts1' 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) prot = Column(Integer, default=22) group_id = Column(Integer, ForeignKey('group1.id')) group = relationship('Group1', backref='host_list')   #添加特殊的字段
 g2 = session.query(Group1).filter(Group1.groupname == 'g2').first()    # 获取组的对象
    print g2.host_list   # 经过自定义的host_list来实现双向的查询
View Code

 

3、原生的SQL与SQLAlchemy  join查询

几个Join的区别 http://stackoverflow.com/questions/38549/difference-between-inner-and-outer-joins 

join查询能够根据两张表中有关联的数据来对表中的数据作处理。

一、原生SQL查询

 

Inner join # select * from a INNER JOIN b on a.a = b.b; # select a.*,b.* from a,b where a.a = b.b;

# 根据hosts1表中的group_id与group1表中的id来取出交集 # select * from hosts1 INNER JOIN group1 on hosts1.group_id = group1.id;
 Left outer join # select * from a LEFT OUTER JOIN b on a.a = b.b; # select a.*,b.* from a,b where a.a = b.b(+);

# 根据hosts1表中的group_id与group1表中的id来取出左边表中的数据 # select * from hosts1 LEFT OUTER JOIN group1 on hosts1.group_id = group1.id;
 Right outer join # select * from a RIGHT OUTER JOIN b on a.a = b.b; # select a.*,b.* from a,b where a.a(+) = b.b;

# 根据hosts1表中的group_id与group1表中的id来取出右边表中的数据 # select * from hosts1 RIGHT OUTER JOIN group1 on hosts1.group_id = group1.id;
SQL_join

二、SQLAlchemy查询

obj = session.query(Host1).join(Host1.group).all()

三、group by 查询 (这里很懵逼,小弟对原生SQL也不懂)

分类聚合。

    obj = session.query(Host1, func.count(Group1.groupname)).join(Host1.group).group_by(Group1.groupname).all()

上面一行代码解释:

一、基于相同主机组,经过join来查找两张表中交集的数据

二、统计出交集组里包含的主机个数

三、并按主机组名和主机个数显示。

 

 

4、多对多关联

在SQLAlchemy里,多对多的关联一样是经过创建第三张关系表来实现的。在这里须要把建立第三张表放在开始位置,且是经过SQLAlchemy的中间状态来实现的。

#!/usr/bin/env python
# _*_coding:utf-8 _*_

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, func, Table
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine


Base = declarative_base()
engine = create_engine("mysql+mysqldb://root:123456@192.168.1.106:3306/test1", max_overflow=5, echo=False)


# 经过中间状态的方法建立第三张关系表,关联其余两张表
HostToGroup = Table('host_to_group', Base.metadata,
                    Column('host_id', ForeignKey('hostsmsg.id'), primary_key=True),
                    Column('group_id', ForeignKey('GroupMsg.id'), primary_key=True),
                    )


class HostMsg(Base):
    __tablename__ = 'hostsmsg'
    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)
    prot = Column(Integer, default=22)
    group = relationship('GroupMsg', backref='host_list', secondary=HostToGroup)   # 添加第三张表的实例

    # 设置回显对象的详细信息
    def __repr__(self):
        return "<id=%s, hostname=%s, ip_addr=%s>" % (self.id, self.hostname, self.ip_addr)


class GroupMsg(Base):
    __tablename__ = 'GroupMsg'
    id = Column(Integer, primary_key=True)
    groupname = Column(String(64), unique=True, nullable=False)

    def __repr__(self):
        return "<id=%s, groupname=%s>" % (self.id, self.groupname)

基本的多对多的操做:

Base.metadata.create_all(engine)  # 建立全部的表结构

if __name__ == '__main__': SessionCls = sessionmaker(bind=engine) session = SessionCls()    # 链接的实例

# =================== 建立组 =======================

    # g1 = GroupMsg(groupname='g1')
    # g2 = GroupMsg(groupname='g2')
    # g3 = GroupMsg(groupname='g3')
    # g4 = GroupMsg(groupname='g4')
    # g5 = GroupMsg(groupname='g5')
    # session.add_all([g1, g2, g3, g4, g5])


# =================== 建立主机 =======================

    # h1 = HostMsg(hostname='host1', ip_addr='172.16.172.1', prot=55)
    # h2 = HostMsg(hostname='host2', ip_addr='172.16.172.2', prot=56)
    # h3 = HostMsg(hostname='host3', ip_addr='172.16.172.3', prot=57)
    # h4 = HostMsg(hostname='host4', ip_addr='172.16.172.4', prot=58)
    # session.add_all([h1, h2, h3, h4])

    # 根据对象,在建立主机时就肯定主机组
    # g3 = session.query(GroupMsg).filter(GroupMsg.groupname == 'g3').first()
    # g5 = session.query(GroupMsg).filter(GroupMsg.groupname == 'g5').first()
    # h5 = HostMsg(hostname='host5', ip_addr='172.16.172.5', prot=58, group=[g3,g5])

# =================== 建立多对多关联 =======================

    # all_groups = session.query(GroupMsg).all() # 获取全部的主机
    # h2 = session.query(HostMsg).filter(HostMsg.hostname == 'host2').first() # 获取其中一台主机
    # h2.group = all_groups

    # g2 = session.query(GroupMsg).filter(GroupMsg.groupname == 'g2').first() # 获取一个组名
    g3 = session.query(GroupMsg).filter(GroupMsg.groupname == 'g3').first() h3 = session.query(HostMsg).filter(HostMsg.hostname == 'host3').first()   # 获取其中一台主机
    # h3.group = [g2, g3]

    # 查看组包含的主机 主机所属的组
    print "------------------>g3:", g3.host_list print "------------------>h3:", h3.group session.commit()
ManyToMany
相关文章
相关标签/搜索