一、ORM
        连表
              一对多
              1、创建表,主动指定外键约束。

              2、操作。
                          类:repr
                   一对多:
                          单表   
                          连表
                                session.query(表1).join(表2).all( )
                     多对多:
                                1、创建表,额外的关系表。
                                2、filter( )  _in( )  把结果可传进去。             
                                3、relationship
                                     A
                                     A_B ==> 【关系表】 relationship 字段 和 primary_key 字段常放在这里。
                                     B          PS:通过A 找到 A_B 关系的时候,是反向找;
                                                        而通过关系找到某一个,是正向找。
                    提示:1、这个关系表不一定要放在A_B 关系表中,其他地方也能放。比如、可以放在A中。
                              2、关系表不影响具体的代码。

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

engine = create_engine("mysql+pymysql://root:123qwe@192.168.1.100:3306/s08day11", max_overflow=5) #定义引擎。
Base = declarative_base()

# 一对多 例如:一个人只能在一个组里。
class Group(Base):
__tablename__ = 'group'
nid = Column(Integer,primary_key=True,autoincrement=True)
caption = Column(String(32))

class User(Base):
__tablename__ = 'user'
nid = Column(Integer,primary_key=True,autoincrement=True)
username =Column(String(32))
group_id = Column(Integer,ForeignKey('group.nid')) #设置外键约束

#与生成表结构无关,仅用于查询方便
_group_ = relationship("Favor", backref='pers')
# (2)通过对象方式
#这样看起来不方便,可以自己进行自定制,只是让 print 时候好看些。
def __repr__(self): #这里定义什么就可以返回并看到什么。因为在sqlalchemy 中使用了 __repr__()内部规定的方法。
temp = '%s -- %s: %s' % (self.nid,self.username,self.group_id)
return temp

def init_db():
Base.metadata.create_all(engine)

def drop_db():
Base.metadata.drop_all(engine)

# init_db() #创建数据库

Session=sessionmaker(bind=engine) #绑定元信息
session=Session()

####### 添加 插入 数据
session.add(Group(caption='DBA'))
session.add(Group(caption='SA'))
session.add(Group(caption='SA'))

#session.commit()

session.add_all([
User(username='alex',group_id=1),
User(username='eric',group_id=2),
User(username='jack',group_id=3)
])
#session.commit()

############# 单表查询 #################

#1、只是获取 user 表的 用户信息。(1)通过对象方式
ret= session.query(User).filter(User.username == 'alex').all()
print(ret) #ret 有多个对象
obj=ret[0] #获取到了对象
print(obj.nid)
print(obj.username)
print(obj.group.id)

print('================================')

#2、获取所有 user 表用户信息。(2) 通过映射方式
ret=session.query(User.username).all()
print(ret)

############## 连表查询 ###############
sql=session.query(User).join(Group,isouter=True) #isouter 为True 打印出sql语句.
print(sql)

print('=================================')

ret=session.query(User).join(Group,isouter=True).all() #join 联表操作。
print(ret)

print('=================================')
#如果想把两个【表】的内容都拿到的话。
ret=session.query(User,Group).join(Group,isouter=True).all()
print(ret)

ret=session.query(User.username,Group.caption).join(Group,isouter=True).all()
print(ret) #在列表中,有一个元祖,元祖中存放着 User表对象和 Group 表

执行结果:
通过对象的方式展示出来了,如果不想通过对象的话,
[1 -- alex: 1]
1
============================================
[('alex',), ('eric',), ('jack',)]
SELECT "user".nid AS user_nid, "user".username AS user_username, "user".group_id AS user_group_id
FROM "user" LEFT OUTER JOIN "group" ON "group".nid = "user".group_id
============================================
[1 -- alex: 1, 2 -- eric: 2, 3 -- jack: 3]
============================================
[(1 -- alex: 1, <__main__.Group object at 0x000001A19CD9A6D8>), (2 -- eric: 2, <__main__.Group object at 0x000001A19CD9A780>), (3 -- jack: 3, <__main__.Group object at 0x000001A19CD9A828>)]

[('alex', 'DBA'), ('eric', 'SA'), ('jack', 'SA')]

上述中, 通过对象的方式展示出来了,如果不想通过对象的话,
这样的方式很麻烦, 所以 与生成表结构无关,仅用于查询方便
group = relationship("Favor", backref='pers')

于是使用 group=relationship('Group',backref='uuu') 就可以了。


2、使用 relationship 方式不用联表,sqlalchemy 内部帮你联表操作了。

    
【一对多】数据库数据如下:
        


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

engine = create_engine("mysql+pymysql://root:123qwe@10.10.31.99:3306/s08day11", max_overflow=5) #定义引擎。
Base = declarative_base()

############# 正向查找 和反向查找 ################
# 一对多
class Group(Base):
__tablename__ = 'group'
nid = Column(Integer,primary_key=True,autoincrement=True)
caption = Column(String(32))

class User(Base):
__tablename__ = 'user'
nid = Column(Integer,primary_key=True,autoincrement=True)
username =Column(String(32))
group_id = Column(Integer,ForeignKey('group.nid')) #设置外键约束
group=relationship('Group',backref='uuu')
# 释义:这种 backref='uuu' 会在Group表中加上一个 uuu,直接 Group.uuu 表示找到跟这个组对应的所有的用户。

def __repr__(self):
temp = '%s -- %s: %s' % (self.nid,self.username,self.group_id)
return temp

Session=sessionmaker(bind=engine)
session=Session()

Base.metadata.create_all(engine) #创建表

#1、新方式【正向查询】
ret = session.query(User).all()
for obj in ret:
# obj 代表user 表的每一行数据
# obj.group 代指 group 对象。
print(obj.nid, obj.username,'======', obj.group_id ,obj.group_id, obj.group.caption,':=',obj.group )

print('=================','\n')
# 2、【原始方式】; 查询所有DBA的信息。
ret = session.query(User.username,Group.caption).join(Group, isouter=True).filter(Group.caption == 'DBA').all()
print(ret)

print('=================','\n')

# 3、新方式 【返向查询】
obj= session.query(Group).filter(Group.caption=='DBA').first()
print(obj.nid)
print(obj.caption)
print(obj.uuu) #通过反向查找Group表中。找到了关于DBA的组的所有user成员,
# 并以列表返回 [1 -- alex: 1, 2 -- eric: 2, 3 -- jack: 3]

执行结果:
1 alex ====== 1 1 DBA := <__main__.Group object at 0x0000019AB50FA898>
2 eric ====== 2 2 SA := <__main__.Group object at 0x0000019AB50FAA58>
3 jack ====== 3 3 SA := <__main__.Group object at 0x0000019AB50FAC18>
4 alex1 ====== 1 1 DBA := <__main__.Group object at 0x0000019AB50FA898>
=================

[('alex', 'DBA'), ('alex1', 'DBA')]
=================

1
DBA
[1 -- alex: 1, 4 -- alex1: 1]


  • 正向查找和反向查找

一般情况下,foreignKey和relationship 是在一起的。
  当我们通过 Group 表找User表的时候,backref=uuu,没有在此表中定义,所以通过Group 查找User表的时候,为反向查找。

如下图展示:




  • 写成 Table对象也可以。

   过程:由 class类转换为 Table对象 ,下面例子是没有写类 直接写 Table对象也可以,一模一样的。

from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKey
metadata = MetaData()

user = Table('user', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(20)),
)

Host= Table('host', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(20)),
)

engine = create_engine("mysql+mysqldb://root:123@127.0.0.1:3306/s11", max_overflow=5)
metadata.create_all(engine)


3、多对多查询
     想要操作多对多,就要有第三张表的介入。
    
     流程如图:
      
  
  数据库展示:

  






######## 多表查询 ###########
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship

engine = create_engine("mysql+pymysql://root:123qwe@192.168.1.100:3306/day13", max_overflow=5)
Base = declarative_base()

class Host(Base):
__tablename__ = 'host'
nid = Column(Integer, primary_key=True,autoincrement=True)
hostname = Column(String(32))
port = Column(String(32))
ip = Column(String(32))

class HostUser(Base):
__tablename__ = 'host_user'
nid = Column(Integer, primary_key=True,autoincrement=True)
username = Column(String(32))

class HostToHostUser(Base):
__tablename__ = 'host_to_host_user'
nid = Column(Integer, primary_key=True,autoincrement=True)

host_id = Column(Integer,ForeignKey('host.nid'))
host_user_id = Column(Integer,ForeignKey('host_user.nid'))

##### 生产 库表 #######
def init_db():
Base.metadata.create_all(engine)

# init_db()

'''
######生成数据 #######

Session=sessionmaker(bind=engine)
session=Session()

session.add_all([
Host(hostname='c1',port='22',ip='1.1.1.1'),
Host(hostname='c2',port='22',ip='1.1.1.2'),
Host(hostname='c3',port='22',ip='1.1.1.3'),
Host(hostname='c4',port='22',ip='1.1.1.4'),
Host(hostname='c5',port='22',ip='1.1.1.5'),
])
session.commit()

session.add_all([
HostUser(username='root'),
HostUser(username='db'),
HostUser(username='nb'),
HostUser(username='sb'),
])
session.commit()

session.add_all([
HostToHostUser(host_id=1,host_user_id=1),
HostToHostUser(host_id=1,host_user_id=2),
HostToHostUser(host_id=1,host_user_id=3),
HostToHostUser(host_id=2,host_user_id=2),
HostToHostUser(host_id=2,host_user_id=4),
HostToHostUser(host_id=2,host_user_id=3),
])
session.commit() #生成数据按钮
'''

Session=sessionmaker(bind=engine)
session=Session()

#>>>需求来了, 获取c1主机中所有的用户??

1、使用【原始方式】获取 。
host_obj=session.query(Host).filter(Host.hostname == 'c1').first()
print(host_obj.nid) #第一步要找的唯一的【主机的ID】。
#得到了结果 ———>ID为1的值。

2、在第三张关系表中--> 利用【主机host的ID】找到了所有的对应的【用户user的 ID】。
host_2_host_user = session.query(HostToHostUser.host_user_id).filter(HostToHostUser.host_id == host_obj.nid).all()
print(host_2_host_user) #在关系表中拿到了C1【主机的ID】对应的 【全部用户ID】。
#执行结果:————> [(1,),(2,),(3),]的列表。

3、根据【用户user的ID】找到所有用户。
r=zip(*host_2_host_user)
# print(list(r)[0]) #目的:转换 [(1,),(2,),(3),] --->为[1,2,3]
# [1,2,3]

users=session.query(HostUser.username).filter(HostUser.nid.in_(list(r)[0])).all()
print(users)

#执行结果:
#[('root',), ('db',), ('nb',)]

########################################

以上的查询方法太low了,其实可以一句话进行才查找。


  • 多表查询(三)、


############## 多表查询【高逼格】方法 ###################
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship

engine = create_engine("mysql+pymysql://root:123qwe@192.168.1.100:3306/day13", max_overflow=5)
Base = declarative_base()

class Host(Base):
__tablename__ = 'host'
nid = Column(Integer, primary_key=True,autoincrement=True)
hostname = Column(String(32))
port = Column(String(32))
ip = Column(String(32))

class HostUser(Base):
__tablename__ = 'host_user'
nid = Column(Integer, primary_key=True,autoincrement=True)
username = Column(String(32))

class HostToHostUser(Base):
__tablename__ = 'host_to_host_user'
nid = Column(Integer, primary_key=True,autoincrement=True)

host_id = Column(Integer,ForeignKey('host.nid'))
host_user_id = Column(Integer,ForeignKey('host_user.nid'))

host = relationship('Host',backref='h')
host_user = relationship('HostUser',backref='u')

Session=sessionmaker(bind=engine)
session=Session()

########查询结果#######:
host_obj = session.query(Host).filter(Host.hostname == 'c1').first()
print(host_obj)
print(host_obj.nid)
print(host_obj.hostname)
print('=========================','\n')

print(host_obj.h) #第三张表对应的对象。

print('=========================','\n')
for item in host_obj.h:
print(item.host_user,item.host_user.nid,item.host_user.username)

执行结果:
<__main__.Host object at 0x000001447FC99B70>
1
c1

=========================

[<__main__.HostToHostUser object at 0x000001447FC99828>, <__main__.HostToHostUser object at 0x000001447FC99EB8>, <__main__.HostToHostUser object at 0x000001447FC99F28>]
=========================

<__main__.HostUser object at 0x000001447FCAE4E0> 1 root
<__main__.HostUser object at 0x000001447FC64C50> 2 db
<__main__.HostUser object at 0x000001447FC99080> 3 nb



4、更简单的方式:多对多查询
      A  
      AB ==》关系表  foreign relationship
      B    

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

engine = create_engine("mysql+pymysql://root:123qwe@192.168.1.100:3306/day13", max_overflow=5)
Base = declarative_base()

class Host(Base):
__tablename__ = 'host'
nid = Column(Integer, primary_key=True,autoincrement=True)
hostname = Column(String(32))
port = Column(String(32))
ip = Column(String(32))

class HostUser(Base):
__tablename__ = 'host_user'
nid = Column(Integer, primary_key=True,autoincrement=True)
username = Column(String(32))

class HostToHostUser(Base):
__tablename__ = 'host_to_host_user'
nid = Column(Integer, primary_key=True,autoincrement=True)

host_id = Column(Integer,ForeignKey('host.nid'))
host_user_id = Column(Integer,ForeignKey('host_user.nid'))

host = relationship('Host',backref='h')
host_user = relationship('HostUser',backref='u')

Session=sessionmaker(bind=engine)
session=Session()

host_obj = session.query(Host).filter(Host.hostname == 'c1').first()
print(host_obj)
print(host_obj.nid)

print('==============================')
print(host_obj.h) #第三张表对应的对象。

print('===============================','\n')
for item in host_obj.h:
print(item.host_user,item.host_user.nid,item.host_user.username)

执行结果:

<__main__.Host object at 0x000001FDBBA4E630>
1
==============================
[<__main__.HostToHostUser object at 0x000001FDBBA4E2B0>, <__main__.HostToHostUser object at 0x000001FDBBA4E940>, <__main__.HostToHostUser object at 0x000001FDBBA4E9B0>]
===============================

<__main__.HostUser object at 0x000001FDBBA6C048> 1 root
<__main__.HostUser object at 0x000001FDBBA6C208> 2 db
<__main__.HostUser object at 0x000001FDBBA6C3C8> 3 nb




5、更更 简单的方式:多对多查询
      A       ==》foreign 和 relationship
      AB关系表 只需要进行简单的定义。
      B    



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

engine = create_engine("mysql+pymysql://root:123qwe@192.168.1.100:3306/day13", max_overflow=5)
Base = declarative_base()

class Host(Base):
__tablename__ = 'host'
nid = Column(Integer, primary_key=True,autoincrement=True)
hostname = Column(String(32))
port = Column(String(32))
ip = Column(String(32))

host_user = relationship('HostUser',secondary=lambda :HostToHostUser.__table__,backref='h')
# 如果 有lambda的话,则可以关系对应表可以不用 放在上面,可以自由放置。放下面就会报错的;无lambda 的话 ,关系对应表应该放在上面。
无lambda 的话 ,关系对应表应该放在上面。

class HostUser(Base):
__tablename__ = 'host_user'
nid = Column(Integer, primary_key=True,autoincrement=True)
username = Column(String(32))

class HostToHostUser(Base):
__tablename__ = 'host_to_host_user'
nid = Column(Integer, primary_key=True,autoincrement=True)

host_id = Column(Integer,ForeignKey('host.nid'))
host_user_id = Column(Integer,ForeignKey('host_user.nid'))

Session=sessionmaker(bind=engine)
session=Session()

host_obj = session.query(Host).filter(Host.hostname == 'c1').first()
print(host_obj)
print(host_obj.nid)

print('==============================')

print(host_obj.host_user)

# print(host_obj.h) #第三张表对应的对象。

print('===============================')
for item in host_obj.host_user:
print(item.username)



执行结果:
<__main__.Host object at 0x000002E592B8F860>
1
==============================
[<__main__.HostUser object at 0x000002E592B8F550>, <__main__.HostUser object at 0x000002E592B8F518>, <__main__.HostUser object at 0x000002E592B8F7B8>]
===============================
root
db
nb







Part01、sqlalchemy 使用的更多相关文章

  1. sqlalchemy学习

    sqlalchemy官网API参考 原文作为一个Pythoner,不会SQLAlchemy都不好意思跟同行打招呼! #作者:笑虎 #链接:https://zhuanlan.zhihu.com/p/23 ...

  2. tornado+sqlalchemy+celery,数据库连接消耗在哪里

    随着公司业务的发展,网站的日活数也逐渐增多,以前只需要考虑将所需要的功能实现就行了,当日活越来越大的时候,就需要考虑对服务器的资源使用消耗情况有一个清楚的认知.     最近老是发现数据库的连接数如果 ...

  3. 冰冻三尺非一日之寒-mysql(orm/sqlalchemy)

    第十二章  mysql ORM介绍    2.sqlalchemy基本使用 ORM介绍: orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似pyt ...

  4. Python 【第六章】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  5. SQLAlchemy(一)

    说明 SQLAlchemy只是一个翻译的过程,我们通过类来操作数据库,他会将我们的对应数据转换成SQL语句. 运用ORM创建表 #!/usr/bin/env python #! -*- coding: ...

  6. sqlalchemy(二)高级用法

    sqlalchemy(二)高级用法 本文将介绍sqlalchemy的高级用法. 外键以及relationship 首先创建数据库,在这里一个user对应多个address,因此需要在address上增 ...

  7. sqlalchemy(一)基本操作

    sqlalchemy(一)基本操作 sqlalchemy采用简单的Python语言,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型. 安装 需要安装MySQLdb pip install ...

  8. python SQLAlchemy

    这里我们记录几个python SQLAlchemy的使用例子: 如何对一个字段进行自增操作 user = session.query(User).with_lockmode('update').get ...

  9. Python-12-MySQL & sqlalchemy ORM

    MySQL MySQL相关文章这里不在赘述,想了解的点击下面的链接: >> MySQL安装 >> 数据库介绍 && MySQL基本使用 >> MyS ...

随机推荐

  1. 【BZOJ】1621: [Usaco2008 Open]Roads Around The Farm分岔路口(dfs)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1621 这题用笔推一下就懂了的.... 当2|(n-k)时,才能分,否则不能分. 那么dfs即可.. ...

  2. RAID的简单说明

    RAID,为 Redundant Arrays of Independent Disks 的简称,中文为廉价※冗余磁盘阵列 . 磁盘阵列 其实也分为软阵列 (Software Raid) 和硬阵列 ( ...

  3. maven公布jar、aar、war等到中央库(Central Repository)的步骤

    步骤一:注冊账号.申请ticket. 注冊在这里:https://issues.sonatype.org 申请ticket:创建一个issue.注意这里要选OSSRH,且是PROJECT而不是TASK ...

  4. 使用ProcDump工具抓取dump

    首先得到要抓取的进程号 cd %windir%\syswow64\inetsrvappcmd list wp得到pid之后, 在任务管理器里发现w3wp.exe的CPU总在49%-60%左右, 间歇性 ...

  5. 内存泄露,GC相关

    内存泄露就是对象不在GC的掌控之内 下面对象会发生内存泄露现象: 1.没有引用的对象 2.虚,软,弱 引用对象 GC引用的对象指的是 1.JavaStack中引用的对象 2.方法区中静态引用指向的对象 ...

  6. AVR 定时器快速PWM模式使用

    PWM很常用,AVR自带内部PWM功能,分为快速PWM模式和相位修正PWM模式.   我们这里选择方式15 ,由OCR1A保存上限值,由OCR1B保存匹配值,所以输出管脚 OCR1A不能输PWM,只能 ...

  7. Oracle正式发布VirtualBox 5.0.22版本

    甲骨文(Oracle)正式发布了VirtualBox 5.0.22版本,该开源和跨平台虚拟化软件的最新维护版本已经面向所有支持平台开放,引入了诸多新特性和功能改善推荐用户尽早完成升级.新版本在Linu ...

  8. Django学习笔记第六篇--实战练习二--简易实现登录注册功能demo

    一.绪论: 简易实现登录功能demo,并没有使用默认身份验证模块,所以做的也很差,关闭了csrf保护,没有认证处理cookie和session,只是简单实现了功能.另外所谓的验证码功能是伪的. 二. ...

  9. oracle11g安装完成后修改字符集

    author : headsen chen date:2018-05-10  10:27:16 oracle11g完成安装后,由于默认安装的时候无法指定字符集,所以手动修改字符集和10g版本一样的字符 ...

  10. mysql 修改默认配置 提高性能

    解决问题 Lost connection to MySQL server at ‘reading authorization packet’, system error: 0 通过修改 connect ...