1.SQLAlchemy之一对多关系

1.1 创建单表

class Test(Base):
__tablename__ = 'user'
nid = Colume(Integer,primary_key=True,autoincrement=True)
name = Colume(String(32))

1.2 创建一对多

class Team(Base):
__tablename__ = 'team'
tid = Colume(Integer,primary_key=True,autoincrement=True)
caption = Colume(String(32)) class user(Base):
__tablename__ = 'user'
nid = Colume(Integer,primary_key=True,autoincrement=True)
name = Colume(String(32))
team_id = Colume(Integer,ForeignKey('team.gid'))

写完类,接下来就是把类转化为数据库表了。

1.3 生成表、删除表

def init_db():
#根据Base去找它的子类,把所有的子类生成表。
Base.metadata.create_all(engine) def drop_db():
#把Base所有的子类对应表删除。
Base.metadata.drop_all(engine)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://python:python@192.168.0.57:3306/python_mysql", max_overflow=5) Base = declarative_base() # 单表
class Test(Base):
__tablename__ = 'test'
nid = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32)) # 一对多
class Team(Base):
__tablename__ = 'team'
tid = Column(Integer, primary_key=True, autoincrement=True)
caption = Column(String(32)) class user(Base):
__tablename__ = 'user'
nid = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32))
team_id = Column(Integer, ForeignKey('team.tid')) def init_db():
Base.metadata.create_all(engine) def drop_db():
Base.metadata.drop_all(engine) init_db()

执行完上面代码后,就会在对应库生成test、user、group三张表,user表的group_id以group表的gid为外键。

1.4 生成表后开始操作表,添加team表数据

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://python:python@192.168.0.57:3306/python_mysql", max_overflow=5) Base = declarative_base() # 单表
class Test(Base):
__tablename__ = 'test'
nid = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32)) # 一对多
class Team(Base):
__tablename__ = 'team'
tid = Column(Integer, primary_key=True, autoincrement=True)
caption = Column(String(32)) class user(Base):
__tablename__ = 'user'
nid = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32))
team_id = Column(Integer, ForeignKey('team.tid')) def init_db():
Base.metadata.create_all(engine) def drop_db():
Base.metadata.drop_all(engine) # init_db()
# drop_db() Session = sessionmaker(bind=engine)
session = Session() #往team表里插入两条数据
session.add(Team(caption='dba'))
session.add(Team(caption='ddd'))
session.commit()

1.5 添加user表数据

Session = sessionmaker(bind=engine)
session = Session()
#批量添加数据;user表的team_id与team表的tid是有外键的,按理来说要插入的team_id的值必须在team表里有对应的tid值,比如这里插入的tead_id是1、2、3,则team表里的tid至少要有1、2、3,不然会插入失败。
#但是,我发现插入没有对应键值的team_id也不会报错。
session.add_all([
User(name='zzz',team_id=1),
User(name='sss',team_id=2),
User(name='ccc',team_id=3),
])
session.commit()

1.6 查询单表

如果仅仅是查询user表的name值,那不需要联合别的表,直接查询单表即可

ret = session.query(User).filter(User.name=='zzz').all()
obj = ret[0]
print(obj.name) #上面的代码等价于这个:
ret = session.query(User.name).filter(User.name=='zzz').all()
print(ret)

1.7 通过__repr__()方法改变返回值

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://python:python@192.168.0.57:3306/python_mysql", max_overflow=5) Base = declarative_base() # 创建单表
class Users(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(32))
extra = Column(String(16)) __table_args__ = (
UniqueConstraint('id', 'name', name='uix_id_name'),
Index('ix_id_name', 'name', 'extra'),
)
#__repr__方法是注释的,看print(ret)的输出
#def __repr__(self):
# return "%s-%s" %(self.id, self.name) 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(Users(id=1,name='zsc'))
session.commit()
ret = session.query(Users).all()
print(ret)
#结果:
[<__main__.Users object at 0x7f1836e80630>]
没有User类里没有__repr__方法时,session.query(Users).all()返回的是类的对象。
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://python:python@192.168.0.57:3306/python_mysql", max_overflow=5) Base = declarative_base() # 创建单表
class Users(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(32))
extra = Column(String(16)) __table_args__ = (
UniqueConstraint('id', 'name', name='uix_id_name'),
Index('ix_id_name', 'name', 'extra'),
)
#__repr__方法取消注释
def __repr__(self):
return "%s-%s" %(self.id, self.name) 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(Users(id=1,name='zsc'))
session.commit()
ret = session.query(Users).all()
print(ret)
#结果:
[1-zsc]
User类里定义了__repr__方法时,session.query(Users).all()返回的是定义的返回结果。

1.8 联合查询

#创建表时指定了外键
ret = session.query(User.name).join(Team).all()等价于SELECT user.name AS FROM user INNER JOIN team ON team.tid = user.team_id
#用select的话需要用on指定约束条件,用SQLAlchemy就不用指定了。
#用“isouter=True”指定left join
ret = session.query(User.name).join(Team,isouter=True).all()

上面的查询,随便是依赖到了别的表,但是结果只是显示了user表的数据,如果想同时显示user和team表的数据,就得用下面的方法了,

ret = session.query(User.name,Team.caption).join(Team).all()
print(ret)
#结果:
[('zzz', 'dba'), ('sss', 'ddd')]

虽然上面的联合查询已经比直接用select简单了,但是还是很麻烦,所以就有了下面的方法。

1.9 relationship

1.9.1 利用ralationship正向查询

正向查询即是使用做外链的表来查询被外链里的数据

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://python:python@192.168.0.57:3306/python_mysql", max_overflow=5) Base = declarative_base() # 一对多
class Team(Base):
__tablename__ = 'team'
tid = Column(Integer, primary_key=True, autoincrement=True)
caption = Column(String(32)) class User(Base):
__tablename__ = 'user'
nid = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32))
team_id = Column(Integer, ForeignKey('team.tid'))
#加上底下这行后,不用使用.join()也可实现联表查询
#哪个表做外链,就把relationship加到哪个表
favor = relationship("Team", backref='uuu') def init_db():
Base.metadata.create_all(engine) def drop_db():
Base.metadata.drop_all(engine) # init_db()
# drop_db() Session = sessionmaker(bind=engine)
session = Session() ret = session.query(User).all()
for obj in ret:
print(obj.nid,obj.name,obj.favor,obj.favor.tid,obj.favor.caption)
#结果:
1 zzz <__main__.Team object at 0x7f5c10d02a20> 1 dba
2 sss <__main__.Team object at 0x7f5c10d026a0> 2 ddd #可见,ret仅仅是User的query结果,而使用obj.favor就相当于是使用Team表,即可直接操作team表。

1.9.2 利用ralationship实现反向查询

反向查询即是使用被外链的表查询到做外链的数据

class Test(Base):
__tablename__ = 'test'
nid = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32)) # 一对多
class Team(Base):
__tablename__ = 'team'
tid = Column(Integer, primary_key=True, autoincrement=True)
caption = Column(String(32)) class User(Base):
__tablename__ = 'user'
nid = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32))
team_id = Column(Integer, ForeignKey('team.tid'))
favor = relationship("Team", backref='uuu') def init_db():
Base.metadata.create_all(engine) def drop_db():
Base.metadata.drop_all(engine) # init_db()
# drop_db() Session = sessionmaker(bind=engine)
session = Session() ret = session.query(Team).filter(Team.caption == 'dba').all()
print(ret[0].tid)
print(ret[0].caption)
print(ret[0].uuu)
#结果:
1
dba
[<__main__.User object at 0x7f7d3fa5ba20>]
#favor = relationship("Team", backref='uuu')里的uuu的作用就是存储着对应的做外链里的数据;比如user里有7个人是dba组的,这时候print(ret[0].uuu)就会返回7个用户的信息;user里有3个dbb组的,这时候print(ret[0].uuu)就会返回3个相关用户的信息。

除了一对多还是多对多关系,多对多是专门建一个中间表来存储两张表的关联关系。

SQLAlchemy看着麻烦,其实就是记语法而已,多用即可;

先建表,再操作单表,再用连表,在整关系,一对多,多对多。

SQLAlchemy一对多总结的更多相关文章

  1. flask的orm框架(SQLAlchemy)-一对多查询以及多对多查询

    一对多,多对多是什么? 一对多.例如,班级与学生,一个班级对应多个学生,或者多个学生对应一个班级. 多对多.例如,学生与课程,可以有多个学生修同一门课,同时,一门课也有很多学生. 一对多查询 如果一个 ...

  2. sqlalchemy一对多的关系

    #encoding: utf-8 from sqlalchemy import create_engine,Column,Integer,String,Float,func,and_,or_,Text ...

  3. SQLAlchemy 一对多

    下述範例描述了電影同導演的多對一關係.範例中說明了從用戶定義的Python類建立數據表的方法,雙方關係例項的建立方法,以及最終查詢數據的方法:包括延遲載入和預先載入兩種自動生成的SQL查詢. 結構定義 ...

  4. flask 中orm关系映射 sqlalchemy的查询

    flask的orm框架(SQLAlchemy)-一对多查询以及多对多查询   一对多,多对多是什么? 一对多.例如,班级与学生,一个班级对应多个学生,或者多个学生对应一个班级. 多对多.例如,学生与课 ...

  5. 应有dataGridView控件

    using System.Data.SqlClient; namespace UseDataGridView { public partial class Form1 : Form { public ...

  6. [ Flask ] myblog_flask问题集(RESTfull风格)

    VUE问题 前端VUE怎么捕获所有404NOT FOUND的路由呢? [ 解决方案 ] vue-router路由守卫,参考文档:动态路由匹配 对于路由.../edit/<id>,自己能编辑 ...

  7. flask SQLAlchemy中一对多的关系实现

    SQLAlchemy是Python中比较优秀的orm框架,在SQLAlchemy中定义了多种数据库表的对应关系, 其中一对多是一种比较常见的关系.利用flask sqlalchemy实现一对多的关系如 ...

  8. SQLAlchemy 增删改查 一对多 多对多

    1.创建数据表 # ORM中的数据表是什么呢? # Object Relation Mapping # Object - Table 通过 Object 去操纵数据表 # 从而引出了我们的第一步创建数 ...

  9. 用SQLAlchemy创建一对多,多对多关系表

    多对多关系表的创建: 如果建立好多对多关系后,我们就可以通过关系名进行循环查找,比如laowang = Teacher.query.filter(Teacher.name=='laowang').fi ...

随机推荐

  1. cocos2d-x的lua脚本加载CocostudioUI两种方式

    前言 当前版本使用的是quick cocos2dx lua 3.3.UI使用cocostudio编辑器1.6.0.我们在程序里面可以使用两种方式进行解析UI.开始的时候用的是quick的方法, 结果遇 ...

  2. (1) 深入理解Java虚拟机到底是什么?

    好文转载:http://blog.csdn.net/zhangjg_blog/article/details/20380971 什么是Java虚拟机   作为一个Java程序员,我们每天都在写Java ...

  3. JavaEE程序员必读图书大推荐

    下面是我根据多年的阅读和实践经验,给您推荐的一些图书: 第一部分: Java语言篇 1 <Java编程规范> 星级: 适合对象:初级,中级 介绍:作者James Gosling(Java之 ...

  4. 如何使用R语言解决可恶的脏数据

    转自:http://shujuren.org/article/45.html 在数据分析过程中最头疼的应该是如何应付脏数据,脏数据的存在将会对后期的建模.挖掘等工作造成严重的错误,所以必须谨慎的处理那 ...

  5. Oracle的使用

    启动: 1.win+R ---> cmd  -----> sqlplus "/as sysdba"  //以sysdba身份登录(此时可以创建用户,分配权限等) win ...

  6. 在网上看到的一篇文章关于js和php编码的

    解决办法: 采用js对URL中的汉字进行escape编码. <a href="" onclick="window.open('product_list.php?p_ ...

  7. 小白菜初探nodejs

    记得大四那年实习的时候出去找工作,就常常听见大家说node.从那以后,悄然埋下了一颗学习nodejs的心.不过由于基础太薄弱,一直没有学习.加之工作上没有相关应用,就一直搁置到现在. 年会的时候,老大 ...

  8. mac 安装tomcat

    一.下载 首先在tomcat官网下载完整版的 tomcat.tar.gz包,Core下 注: zip用于windows操作系统,tar.gz用于unix和linux操作系统. Binary Distr ...

  9. [http session]

    原文链接:http://lavasoft.blog.51cto.com/62575/275589/ 1.Session创建的时间是: 一个常见的误解是以为session在有客户端访问时就被创建,然而事 ...

  10. c++虚函数的作用是什么?

    <深入浅出MFC>中形容虚函数是执行一般化操作,一直没有领悟要点.现在的体悟是抽象,先前考虑问题都是由抽象到具象,比如下文中的示例,由上(虚基类的「怪物」)至下(派生类的三个子类「狼」「蜘 ...