參考:

http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#building-a-relationship

http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#working-with-related-objects

建立表之间带关系

建立外建

在address加入user的外键

  1. from sqlalchemy import ForeignKey, Column, String, Integer
  2. from sqlalchemy.orm import relationship
  3. class User(Base):
  4. __tablename__ = 'users'
  5. id = Column(Integer, primary_key=True)
  6. name = Column(String)
  7. fullname = Column(String)
  8. password = Column(String)
  9. class Address(Base):
  10. __tablename__ = 'addresses'
  11. id = Column(Integer, primary_key=True)
  12. email_address = Column(String, nullable=False)
  13. user_id = Column(Integer, ForeignKey('users.id'))
  14. user = relationship('User', backref=backref('addresses', order_by=id))

relationship中的backref參数使用形式:

  1. backref="addresses" #直接使用表名的字符串
  2. backref=backref('addresses') #使用backref函数
  3. backref=backref('addresses', order_by=id)) #brackref函数能够加入參数,详见http://docs.sqlalchemy.org/en/rel_1_0/orm/backref.html#backref-arguments

能够使用user.addresses 从user获取address 和,使用address.users 虫address获取user

backref 会在User跟Address上都加上关系,它本质是:

  1. from sqlalchemy import Integer, ForeignKey, String, Column
  2. from sqlalchemy.ext.declarative import declarative_base
  3. from sqlalchemy.orm import relationship
  4. Base = declarative_base()
  5. class User(Base):
  6. __tablename__ = 'user'
  7. id = Column(Integer, primary_key=True)
  8. name = Column(String)
  9. addresses = relationship("Address", back_populates="user")
  10. class Address(Base):
  11. __tablename__ = 'address'
  12. id = Column(Integer, primary_key=True)
  13. email = Column(String)
  14. user_id = Column(Integer, ForeignKey('user.id'))
  15. user = relationship("User", back_populates="addresses")

relationship中的

加入

  1. >>> jack.addresses = [
  2. ... Address(email_address='jack@google.com'),
  3. ... Address(email_address='j25@yahoo.com')]

获取

  1. >>> jack.addresses[1]
  2. <Address(email_address='j25@yahoo.com')>
  3. >>> jack.addresses[1].user
  4. <User(name='jack', fullname='Jack Bean', password='gjffdd')>

commit

  1. session.add(jack)
  2. session.commit()

address 会自己主动的加入

one to many 关系

  1. class Parent(Base):
  2. __tablename__ = 'parent'
  3. id = Column(Integer, primary_key=True)
  4. children = relationship("Child", backref="parent")
  5. class Child(Base):
  6. __tablename__ = 'child'
  7. id = Column(Integer, primary_key=True)
  8. parent_id = Column(Integer, ForeignKey('parent.id'))

many to one 关系

  1. class Parent(Base):
  2. __tablename__ = 'parent'
  3. id = Column(Integer, primary_key=True)
  4. child_id = Column(Integer, ForeignKey('child.id'))
  5. child = relationship("Child", backref="parents")
  6. class Child(Base):
  7. __tablename__ = 'child'
  8. id = Column(Integer, primary_key=True)

one to one 关系

  1. from sqlalchemy.orm import backref
  2. class Parent(Base):
  3. __tablename__ = 'parent'
  4. id = Column(Integer, primary_key=True)
  5. child_id = Column(Integer, ForeignKey('child.id'))
  6. child = relationship("Child", backref=backref("parent", uselist=False))
  7. class Child(Base):
  8. __tablename__ = 'child'
  9. id = Column(Integer, primary_key=True)

many to many 关系

须要一个中间表和在relatonship 加入secondary參数

  1. association_table = Table('association', Base.metadata,
  2. Column('left_id', Integer, ForeignKey('left.id')),
  3. Column('right_id', Integer, ForeignKey('right.id'))
  4. )
  5. class Parent(Base):
  6. __tablename__ = 'left'
  7. id = Column(Integer, primary_key=True)
  8. children = relationship("Child",
  9. secondary=association_table,
  10. backref="parents")
  11. class Child(Base):
  12. __tablename__ = 'right'
  13. id = Column(Integer, primary_key=True)

这样在child加入删除parent或者parent加入删除child时,无需对中间表进行操作。直接加入删除就可以。

  1. parent.children.append(child)
  2. child.parents.append(parent)

也能够 使用类来创建中间表,这样能够在中间表中保存一些其它的信息。可是就不能想前面一样自己主动对中间表进行操作。

  1. class Association(Base):
  2. __tablename__ = 'association'
  3. left_id = Column(Integer, ForeignKey('left.id'), primary_key=True)
  4. right_id = Column(Integer, ForeignKey('right.id'), primary_key=True)
  5. extra_data = Column(String(50))
  6. child = relationship("Child", back_populates="parents")
  7. parent = relationship("Parent", back_populates="children")
  8. class Parent(Base):
  9. __tablename__ = 'left'
  10. id = Column(Integer, primary_key=True)
  11. children = relationship("Association", back_populates="parent")
  12. class Child(Base):
  13. __tablename__ = 'right'
  14. id = Column(Integer, primary_key=True)
  15. parents = relationship("Association", back_populates="child")

join 操作

能够使用Query.join()

  1. >>> session.query(User).join(Address).\
  2. ... filter(Address.email_address=='jack@google.com').\
  3. ... all()
  4. [<User(name='jack', fullname='Jack Bean', password='gjffdd')>]

在User上能够直接使用join(Address) 由于仅仅有一个外建在User和Address之间,其它join形式:

  1. query.join(Address, User.id==Address.user_id) # explicit condition
  2. query.join(User.addresses) # specify relationship from left to right
  3. query.join(Address, User.addresses) # same, with explicit target
  4. query.join('addresses') # same, using a string

使用外链接

  1. query.outerjoin(User.addresses) # 默认是左外连接。

当query中有多个实体点使用,使用join默认join追左边的那个,

比如:

  1. query = session.query(User, Address).join(User) # 报错
  2. query = session.query(Address User).join(User) # 正确

假设想自定使用join那个表。能够使用select_form

  1. query = Session.query(User, Address).select_from(Address).join(User)

alias 别名

假设想join自己,能够使用别名

  1. from sqlalchemy.orm import aliased
  2. adalias1 = aliased(Address)
  3. adalias2 = aliased(Address)
  4. for username, email1, email2 in \
  5. session.query(User.name, adalias1.email_address, adalias2.email_address).\
  6. join(adalias1, User.addresses).\
  7. join(adalias2, User.addresses).\
  8. filter(adalias1.email_address=='jack@google.com').\
  9. filter(adalias2.email_address=='j25@yahoo.com'):
  10. print(username, email1, email2)

使用子查询

直接看官方文档的样例:

  1. >>> from sqlalchemy.sql import func
  2. >>> stmt = session.query(Address.user_id, func.count('*').\
  3. ... label('address_count')).\
  4. ... group_by(Address.user_id).subquery()
  5. >>> for u, count in session.query(User, stmt.c.address_count).\
  6. ... outerjoin(stmt, User.id==stmt.c.user_id).order_by(User.id):
  7. ... print(u, count)
  8. <User(name='ed', fullname='Ed Jones', password='f8s7ccs')> None
  9. <User(name='wendy', fullname='Wendy Williams', password='foobar')> None
  10. <User(name='mary', fullname='Mary Contrary', password='xxg527')> None
  11. <User(name='fred', fullname='Fred Flinstone', password='blah')> None
  12. <User(name='jack', fullname='Jack Bean', password='gjffdd')> 2

使用EXISTS

看官方文档的样例:

  1. >>> from sqlalchemy.sql import exists
  2. >>> stmt = exists().where(Address.user_id==User.id)
  3. SQL>>> for name, in session.query(User.name).filter(stmt):
  4. ... print(name)
  5. jack

等价于:

  1. >>> for name, in session.query(User.name).\
  2. ... filter(User.addresses.any()):
  3. ... print(name)
  4. jack

user.addresses 能够像user中其它属性一样在filter使用==、!=、any等等。

  1. query.filter(Address.user == someuser)
  2. query.filter(Address.user != someuser)
  3. query.filter(Address.user == None)
  4. query.filter(User.addresses.contains(someaddress))
  5. query.filter(User.addresses.any(Address.email_address == 'bar'))# also takes keyword arguments:
  6. query.filter(User.addresses.any(email_address='bar'))
  7. query.filter(Address.user.has(name='ed'))
  8. session.query(Address).with_parent(someuser, 'addresses')

SQLAlchemy使用笔记--SQLAlchemy ORM(二)的更多相关文章

  1. SQLAlchemy 学习笔记(二):ORM

    照例先看层次图 一.声明映射关系 使用 ORM 时,我们首先需要定义要操作的表(通过 Table),然后再定义该表对应的 Python class,并声明两者之间的映射关系(通过 Mapper). 方 ...

  2. SQLAlchemy 学习笔记(三):ORM 中的关系构建

    个人笔记,不保证正确. 关系构建:ForeignKey 与 relationship 关系构建的重点,在于搞清楚这两个函数的用法.ForeignKey 的用法已经在 SQL表达式语言 - 表定义中的约 ...

  3. SQLAlchemy使用笔记--SQLAlchemy ORM(三)

    參考: http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#eager-loading 预先载入 前面的代码,由于是lazy load.当我 ...

  4. SQLAlchemy 学习笔记(一):Engine 与 SQL 表达式语言

    个人笔记,如有错误烦请指正. SQLAlchemy 是一个用 Python 实现的 ORM (Object Relational Mapping)框架,它由多个组件构成,这些组件可以单独使用,也能独立 ...

  5. Sqlalchemy python经典第三方orm

    Ⅰ. 安装 pip install sqlalchemy Ⅱ. 起步链接 import time import threading import sqlalchemy from sqlalchemy ...

  6. Django和SQLAlchemy,哪个Python ORM更好?

    ORM是什么? 在介绍Python下的两个ORM框架(Django和SQLAlchemy)的区别之前,我们首先要充分了解ORM框架的用途. ORM代表对象关系映射.ORM中的每个单词解释了他们在实际项 ...

  7. SQLAlchemy 简单笔记

    ORM 江湖##### 曾几何时,程序员因为惧怕SQL而在开发的时候小心翼翼的写着sql,心中总是少不了恐慌,万一不小心sql语句出错,搞坏了数据库怎么办?又或者为了获取一些数据,什么内外左右连接,函 ...

  8. Python与数据库[2] -> 关系对象映射/ORM[3] -> sqlalchemy 的声明层 ORM 访问方式

    sqlalchemy的声明层ORM访问方式 sqlalchemy中可以利用声明层进行表格类的建立,并利用ORM对象进行数据库的操作及访问,另一种方式为显式的 ORM 访问方式. 主要的建立步骤包括: ...

  9. Python与数据库[2] -> 关系对象映射/ORM[4] -> sqlalchemy 的显式 ORM 访问方式

    sqlalchemy 的显式 ORM 访问方式 对于sqlalchemy,可以利用一种显式的ORM方式进行访问,这种方式无需依赖声明层,而是显式地进行操作.还有一种访问方式为声明层 ORM 访问方式. ...

随机推荐

  1. jQuery 中的 unbind() 方法

    jQuery 中的 unbind() 方法是 bind() 方法的反向操作,从每一个匹配的元素中删除绑定的事件. 语法结构: unbind([type][, data]); type是事件类型,dat ...

  2. io流中比较特殊的流-java

    1.序列流(SequenceInputStream)整合个多个文件 A SequenceInputStream表示其他输入流的逻辑级联. 它从一个有序的输入流集合开始,从第一个读取到文件的结尾,然后从 ...

  3. MySQL关键字大全

    转载自:https://blog.csdn.net/benxiaohai888/article/details/77803090 在使用MySQL的时候,一般尽量避免用关键字作为表名,如使用关键字做表 ...

  4. 《java并发编程实战》读书笔记1--线程安全性,内置锁,重入,状态

    什么是线程安全? 当多个线程访问某个类时,不管这些的线程的执行顺序如何,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的. 哈哈书上的解释,还是翻译过 ...

  5. Jmeter----读取excel表中的数据

    Jmeter 读取excel数据使用的方法是使用CSV Data Set Config参数化,之后使用BeanShell Sampler来读取excel表中的数据 第一步.查看所需的接口都要哪些字段和 ...

  6. AC日记——旅游 bzoj 2157

    2157 思路: LCT: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 400005 #define IN ...

  7. IllegalStateException: Unable to find a @SpringBootConfiguration

    此处需要改掉包名和类名

  8. Maven的私有仓库Nexus

    1.什么是Nexus 在前面进行maven项目的构建中,可以看到在构建的过程中需要安装maven的依赖插件,如图: 在日常的开发构建中,我们也可以自己搭建一个私有的nexus.那么什么是nexus呢? ...

  9. Rsync+Inotify 搭建实时同步数据

    1.安装软件包 # yum install inotify-tools # yum -y install rsync 2.同步机器相互添加信任 [root@host-10-0-100-106 ~]# ...

  10. 转:libFuzzer Tutorial(libFuzzer教程)

    转:https://github.com/google/fuzzer-test-suite/blob/master/tutorial/libFuzzerTutorial.md 本文在Ubuntu16下 ...