參考:

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的外键

from sqlalchemy import ForeignKey, Column, String, Integer
from sqlalchemy.orm import relationship class User(Base):
__tablename__ = 'users' id = Column(Integer, primary_key=True)
name = Column(String)
fullname = Column(String)
password = Column(String) class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
email_address = Column(String, nullable=False)
user_id = Column(Integer, ForeignKey('users.id'))
user = relationship('User', backref=backref('addresses', order_by=id))

relationship中的backref參数使用形式:

backref="addresses" #直接使用表名的字符串
backref=backref('addresses') #使用backref函数
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上都加上关系,它本质是:

from sqlalchemy import Integer, ForeignKey, String, Column
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship Base = declarative_base() class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String) addresses = relationship("Address", back_populates="user") class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
email = Column(String)
user_id = Column(Integer, ForeignKey('user.id')) user = relationship("User", back_populates="addresses")

relationship中的

加入

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

获取

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

commit

session.add(jack)
session.commit()

address 会自己主动的加入

one to many 关系

class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship("Child", backref="parent") class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))

many to one 关系

class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
child_id = Column(Integer, ForeignKey('child.id'))
child = relationship("Child", backref="parents") class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)

one to one 关系

from sqlalchemy.orm import backref

class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
child_id = Column(Integer, ForeignKey('child.id'))
child = relationship("Child", backref=backref("parent", uselist=False)) class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)

many to many 关系

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

association_table = Table('association', Base.metadata,
Column('left_id', Integer, ForeignKey('left.id')),
Column('right_id', Integer, ForeignKey('right.id'))
) class Parent(Base):
__tablename__ = 'left'
id = Column(Integer, primary_key=True)
children = relationship("Child",
secondary=association_table,
backref="parents") class Child(Base):
__tablename__ = 'right'
id = Column(Integer, primary_key=True)

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

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

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

class Association(Base):
__tablename__ = 'association'
left_id = Column(Integer, ForeignKey('left.id'), primary_key=True)
right_id = Column(Integer, ForeignKey('right.id'), primary_key=True)
extra_data = Column(String(50))
child = relationship("Child", back_populates="parents")
parent = relationship("Parent", back_populates="children") class Parent(Base):
__tablename__ = 'left'
id = Column(Integer, primary_key=True)
children = relationship("Association", back_populates="parent") class Child(Base):
__tablename__ = 'right'
id = Column(Integer, primary_key=True)
parents = relationship("Association", back_populates="child")

join 操作

能够使用Query.join()

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

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

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

使用外链接

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

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

比如:

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

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

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

alias 别名

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

from sqlalchemy.orm import aliased

adalias1 = aliased(Address)
adalias2 = aliased(Address) for username, email1, email2 in \
session.query(User.name, adalias1.email_address, adalias2.email_address).\
join(adalias1, User.addresses).\
join(adalias2, User.addresses).\
filter(adalias1.email_address=='jack@google.com').\
filter(adalias2.email_address=='j25@yahoo.com'):
print(username, email1, email2)

使用子查询

直接看官方文档的样例:

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

使用EXISTS

看官方文档的样例:

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

等价于:

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

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

query.filter(Address.user == someuser)
query.filter(Address.user != someuser)
query.filter(Address.user == None)
query.filter(User.addresses.contains(someaddress)) query.filter(User.addresses.any(Address.email_address == 'bar'))# also takes keyword arguments:
query.filter(User.addresses.any(email_address='bar')) query.filter(Address.user.has(name='ed'))
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. iframe子页面获取父页面元素和window对象

    项目中发现要在iframe的弹框中获取父页面中的元素,我们可以按照如下代码操作:$(window.parent.document).find('selector').attr('XXX') 如果我们需 ...

  2. 线程同步工具 Semaphore类的基础使用

    推荐好文: 线程同步工具(一) 线程同步工具(二)控制并发访问多个资源 并发工具类(三)控制并发线程数的Semaphore 简介 Semaphore是基于计数的信号量,可以用来控制同时访问特定资源的线 ...

  3. 小程序的一个tab切换

    <view class="tab-left" bindtap="tab"> <view class="{{tabArr.curHdI ...

  4. Linux下undefined reference to ‘pthread_create’问题解决 zz

    接触了Linux系统编程中的线程编程模块,可gcc sample.c(习惯把书上的sample代码写进sample.c文件中)出现“undefined reference to ‘pthread_cr ...

  5. window下线程同步之(Semaphores(信号量))

    HANDLE WINAPI CreateSemaphore( _In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes _In_ LONG lIniti ...

  6. MySQL中的内连接、外连接、交叉连接

    内连接(INNER JOIN):   分为三种 等值连接.自然连接.不等连接        外连接(OUTER JOIN):   左外连接(LEFT OUTER JOIN或LEFT JOIN)   右 ...

  7. flex布局各种情况总结分析及实例演示

    2009年,W3C提出了一种新的方案----Flex布局,可以简便.完整.响应式地实现各种页面布局.目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能. 通过笔者大量实践,发现 ...

  8. npoi的用法,动态的判断单元格的大小,设置列的宽度

    public MemoryStream GridToExcelByNPOI(DataTable dt, string strExcelFileName) { HSSFWorkbook wk = new ...

  9. Flask实战第44天:完成前台注册功能

    注册功能后端逻辑 用户注册要把注册的表单提交上来,因此,我要先对表单进行验证,编辑front.forms from apps.forms import BaseForm from wtforms im ...

  10. Xamarin iOS项目找不到模拟器

    Xamarin iOS项目找不到模拟器 在Visual Studio中,突然找不到模拟器,并且项目提示试用期过期:Trial period has expired.出现这种情况,是由于苹果系统中Xam ...