转自:https://www.cnblogs.com/coder2012/p/4746941.html

外键以及relationship

首先创建数据库,在这里一个user对应多个address,因此需要在address上增加user_id这个外键(一对多)。

#!/usr/bin/env python
# encoding: utf-8 from sqlalchemy import create_engine
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy import ForeignKey
from sqlalchemy.orm import backref
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class User(Base):
__tablename__ = 'users' id = Column(Integer, primary_key=True)
name = Column(String(32)) addresses = relationship("Address", order_by="Address.id", backref="user") class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
email_address = Column(String(32), nullable=False)
user_id = Column(Integer, ForeignKey('users.id')) #user = relationship("User", backref=backref('addresses', order_by=id)) engine = create_engine('mysql://root:root@localhost:3306/test', echo=True)
#Base.metadata.create_all(engine)

接下来,调用user和address来添加数据,

>>> jack = User(name='jack')
>>> jack.address
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'User' object has no attribute 'address'
>>> jack.addresses
[]
>>> jack.addresses = [Address(email_address='test@test.com'), Address(email_address='test1@test1.com')]
>>> jack.addresses
[<demo.Address object at 0x7f2536564f90>, <demo.Address object at 0x7f2535dc71d0>]
>>> session.add(jack)
>>> session.commit()
2015-08-19 13:45:36,237 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'
2015-08-19 13:45:36,237 INFO sqlalchemy.engine.base.Engine ()
2015-08-19 13:45:36,238 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
2015-08-19 13:45:36,238 INFO sqlalchemy.engine.base.Engine ()
2015-08-19 13:45:36,239 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = 'utf8' and `Collation` = 'utf8_bin'
2015-08-19 13:45:36,239 INFO sqlalchemy.engine.base.Engine ()
2015-08-19 13:45:36,239 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
2015-08-19 13:45:36,239 INFO sqlalchemy.engine.base.Engine ()
2015-08-19 13:45:36,240 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
2015-08-19 13:45:36,240 INFO sqlalchemy.engine.base.Engine ()
2015-08-19 13:45:36,240 INFO sqlalchemy.engine.base.Engine SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin AS anon_1
2015-08-19 13:45:36,240 INFO sqlalchemy.engine.base.Engine ()
2015-08-19 13:45:36,241 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2015-08-19 13:45:36,242 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name) VALUES (%s)
2015-08-19 13:45:36,242 INFO sqlalchemy.engine.base.Engine ('jack',)
2015-08-19 13:45:36,243 INFO sqlalchemy.engine.base.Engine INSERT INTO addresses (email_address, user_id) VALUES (%s, %s)
2015-08-19 13:45:36,243 INFO sqlalchemy.engine.base.Engine ('test@test.com', 1L)
2015-08-19 13:45:36,243 INFO sqlalchemy.engine.base.Engine INSERT INTO addresses (email_address, user_id) VALUES (%s, %s)
2015-08-19 13:45:36,243 INFO sqlalchemy.engine.base.Engine ('test1@test1.com', 1L)
2015-08-19 13:45:36,244 INFO sqlalchemy.engine.base.Engine COMMIT
>>>

此时,查看数据库,可以得到刚才插入的数据,

mysql> select * from users;
+----+------+
| id | name |
+----+------+
| 1 | jack |
+----+------+
1 row in set (0.00 sec) mysql> select * from addresses;
+----+-----------------+---------+
| id | email_address | user_id |
+----+-----------------+---------+
| 1 | test@test.com | 1 |
| 2 | test1@test1.com | 1 |
+----+-----------------+---------+
2 rows in set (0.00 sec)

join查询

如果不使用join的话,可以直接联表查询,

>>> session.query(User.name, Address.email_address).filter(User.id==Address.user_id).filter(Address.email_address=='test@test.com').all()
2015-08-19 14:02:02,877 INFO sqlalchemy.engine.base.Engine SELECT users.name AS users_name, addresses.email_address AS addresses_email_address
FROM users, addresses
WHERE users.id = addresses.user_id AND addresses.email_address = %s
2015-08-19 14:02:02,878 INFO sqlalchemy.engine.base.Engine ('test@test.com',)
[('jack', 'test@test.com')]

在sqlalchemy中提供了Queqy.join()函数,

>>> session.query(User).join(Address).filter(Address.email_address=='test@test.com').first()
2015-08-19 14:06:56,624 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id, users.name AS users_name
FROM users INNER JOIN addresses ON users.id = addresses.user_id
WHERE addresses.email_address = %s
LIMIT %s
2015-08-19 14:06:56,624 INFO sqlalchemy.engine.base.Engine ('test@test.com', 1)
<demo.User object at 0x7f9a74139a10>
>>> session.query(User).join(Address).filter(Address.email_address=='test@test.com').first().name
2015-08-19 14:07:04,224 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id, users.name AS users_name
FROM users INNER JOIN addresses ON users.id = addresses.user_id
WHERE addresses.email_address = %s
LIMIT %s
2015-08-19 14:07:04,224 INFO sqlalchemy.engine.base.Engine ('test@test.com', 1)
'jack'
>>> session.query(User).join(Address).filter(Address.email_address=='test@test.com').first().addresses
2015-08-19 14:07:06,534 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id, users.name AS users_name
FROM users INNER JOIN addresses ON users.id = addresses.user_id
WHERE addresses.email_address = %s
LIMIT %s
2015-08-19 14:07:06,534 INFO sqlalchemy.engine.base.Engine ('test@test.com', 1)
2015-08-19 14:07:06,535 INFO sqlalchemy.engine.base.Engine SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id
FROM addresses
WHERE %s = addresses.user_id ORDER BY addresses.id
2015-08-19 14:07:06,535 INFO sqlalchemy.engine.base.Engine (1L,)
[<demo.Address object at 0x7f9a74139350>, <demo.Address object at 0x7f9a741390d0>]
>>>

注意,上面的用法的前提是存在外键的情况下,如果没有外键,那么可以使用,

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')

表的别名

>>> from sqlalchemy.orm import aliased
>>> adalias1 = aliased(Address)

子查询

假设我们需要这样一个查询,

mysql> SELECT users.*, adr_count.address_count FROM users LEFT OUTER JOIN
-> (SELECT user_id, count(*) AS address_count
-> FROM addresses GROUP BY user_id) AS adr_count
-> ON users.id=adr_count.user_id;
+----+------+---------------+
| id | name | address_count |
+----+------+---------------+
| 1 | jack | 2 |
+----+------+---------------+
1 row in set (0.00 sec)
# 生成子句,等同于(select user_id ... group_by user_id)
>>> sbq = session.query(Address.user_id, func.count('*').label('address_count')).group_by(Address.user_id).subquery() # 联接子句,注意子句中需要使用c来调用字段内容
>>> session.query(User.name, sbq.c.address_count).outerjoin(sbq, User.id==sbq.c.user_id).all()
2015-08-19 14:42:53,425 INFO sqlalchemy.engine.base.Engine SELECT users.name AS users_name, anon_1.address_count AS anon_1_address_count
FROM users LEFT OUTER JOIN (SELECT addresses.user_id AS user_id, count(%s) AS address_count
FROM addresses GROUP BY addresses.user_id) AS anon_1 ON users.id = anon_1.user_id
2015-08-19 14:42:53,425 INFO sqlalchemy.engine.base.Engine ('*',)
[('jack', 2L)]
>>>

包含contains

query.filter(User.addresses.contains(someaddress))

数据删除delete

>>> session.delete(jack)
>>> session.query(User).filter_by(name='jack').count()
0

外键配置

在上面的例子中,删除了user-jack,但是address中的数据并没有删除。

cascade字段用来

addresses = relationship("Address", backref='user',
cascade="all, delete, delete-orphan")

sqlalchemy(二)高级用法 2的更多相关文章

  1. sqlalchemy(二)高级用法

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

  2. 【iOS开发】Alamofire框架的使用二 高级用法

    Alamofire是在URLSession和URL加载系统的基础上写的.所以,为了更好地学习这个框架,建议先熟悉下列几个底层网络协议栈: URL Loading System Programming ...

  3. redis(二)高级用法

    redis(二)高级用法 事务 redis的事务是一组命令的集合.事务同命令一样都是redis的最小执行单元,一个事务中的命令要么执行要么都不执行. 首先需要multi命令来开始事务,用exec命令来 ...

  4. C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

    原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | I ...

  5. SolrNet高级用法(分页、Facet查询、任意分组)

    前言 如果你在系统中用到了Solr的话,那么肯定会碰到从Solr中反推数据的需求,基于数据库数据生产索引后,那么Solr索引的数据相对准确,在电商需求中经常会碰到菜单.导航分类(比如电脑.PC的话会有 ...

  6. 再谈Newtonsoft.Json高级用法

    上一篇Newtonsoft.Json高级用法发布以后收到挺多回复的,本篇将分享几点挺有用的知识点和最近项目中用到的一个新点进行说明,做为对上篇文章的补充. 阅读目录 动态改变属性序列化名称 枚举值序列 ...

  7. Newtonsoft.Json高级用法(转)

    手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数 ...

  8. [.net 面向对象程序设计进阶] (3) 正则表达式 (二) 高级应用

    [.net 面向对象程序设计进阶] (2) 正则表达式 (二)  高级应用 上一节我们说到了C#使用正则表达式的几种方法(Replace,Match,Matches,IsMatch,Split等),还 ...

  9. 【转】 Newtonsoft.Json高级用法

    手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数 ...

随机推荐

  1. 点滴积累【JS】---JS小功能(onmousemove鼠标移动坐标接龙DIV)

    效果: 思路: 利用onmousemove事件,然后获取鼠标的坐标,之后把DIV挨个遍历,最后把鼠标的坐标赋给DIV. 代码: <head runat="server"> ...

  2. swift -变量的定义与使用

    使⽤用let来声明常量,使⽤用var来声明变量. ⼀一个常量的值在编译时并不须要获取,可是你仅仅能为它赋值⼀一次.也就是说你能够⽤用常量来表⽰示这样⼀一个值:你仅仅须要决定⼀一次,可是须要使⽤用非常多 ...

  3. 蓝牙(CoreBluetooth)-外部设备(服务端)

    蓝牙(CoreBluetooth)-外部设备(服务端) 主要内容 1. 创建外部管理器对象 2. 设置本地外设的服务和特征 3. 添加服务和特征到到你的设置的数据库中 4. 向外公布你的的服务 5. ...

  4. 解决:std::ostream operator<< should have been declared inside 'xxx'

    用VS的NMAKE构建,不会报错,但是用GNU MAKE构建,就会报错.(尝试删除Toast.h中第24行的声明) 因此在遇到类似的情况的时候,记得不仅class里面要有friend声明,namesp ...

  5. cocos2dx触摸

    两种方法其实都一样,CCLayer也是继承CCTouchDelegate. 1.继承CCTouchDelegate 添加触摸代理 CCTouchDispatcher* pDispatcher = CC ...

  6. ecmall的物流配送体系改造

    接触多了ecshop.ecmall原始逻辑的,一般都习惯以整单的方式统一计算运费,这是一种很简单的思路. 但淘宝多了,就发现,物流运费没有那么简单. 首先,每种商品单独设置运费的体系,或者叫运费模板: ...

  7. Centos + HHVM 生产环境安装!

    一.配置防火墙,开启80端口.3306端口 CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙. 1.关闭firewall: systemctl stop fi ...

  8. HTTP与HTTPS异同/HTTP1.0与HTTP1.1差别

    HTTP状态码 分类 解释 描述 1XX 信息 服务器收到请求,需要请求者继续执行操作 2XX 成功 操作被成功接收并处理 3XX 重定向 需要进一步的操作以完成请求 4XX 客户端错误 请求包含语法 ...

  9. 【C++自我精讲】基础系列三 重载

    [C++自我精讲]基础系列三 重载 0 前言 分二部分:函数重载,操作符重载. 1 函数重载 函数重载:指在同一名字空间中,函数名称相同,参数类型.顺序或数量不同的一类函数,同一函数名的函数能完成不同 ...

  10. CSS径向渐变radial-gradient

    可以做一些效果,不错! 网址:http://www.cnblogs.com/xiaohuochai/p/5383285.html