当前位置: 首页 > news >正文

sqlalchemy(二)高级用法

本文将介绍sqlalchemy的高级用法。

外键以及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")

知识共享许可协议
本文 由 cococo点点 创作,采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议进行许可。欢迎转载,请注明出处:
转载自:cococo点点 http://www.cnblogs.com/coder2012


相关文章:

  • eclipse properties 插件
  • CLR存储过程
  • 经典-输出规律的数字序列
  • 运维经验分享(四)--关于 java进程管理的服务控制脚本编程思路分析
  • datepicker使用
  • Xargs用法详解(原创)
  • 外部程序调用跨数据库的语句时:该事务管理器已经禁止了它对远程/网络事务的支持...
  • jQuery对象入门级介绍
  • Flexbox-CSS3弹性盒模型flexbox完整版教程
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • EF 增删改查 泛型方法、类
  • MongoDB 是如何鼓励和激励开发者社区的
  • dubbo源码分析系列——dubbo的SPI机制源码分析
  • Elasticsearch数据建模-关联查询
  • Ubuntu/Linux 笔记应用 为知笔记(支持markdown)
  • co模块的前端实现
  • express如何解决request entity too large问题
  • go语言学习初探(一)
  • iOS 系统授权开发
  • MySQL-事务管理(基础)
  • Mysql数据库的条件查询语句
  • PHP 7 修改了什么呢 -- 2
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • spring cloud gateway 源码解析(4)跨域问题处理
  • uva 10370 Above Average
  • 代理模式
  • 复习Javascript专题(四):js中的深浅拷贝
  • 力扣(LeetCode)357
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 源码安装memcached和php memcache扩展
  • PostgreSQL之连接数修改
  • 国内开源镜像站点
  • 昨天1024程序员节,我故意写了个死循环~
  • # 计算机视觉入门
  • (C语言)球球大作战
  • (论文阅读40-45)图像描述1
  • (实战篇)如何缓存数据
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .form文件_一篇文章学会文件上传
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .Net Core 中间件验签
  • .net framework profiles /.net framework 配置
  • .NET 解决重复提交问题
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • /dev下添加设备节点的方法步骤(通过device_create)
  • @JsonFormat与@DateTimeFormat注解的使用
  • @modelattribute注解用postman测试怎么传参_接口测试之问题挖掘
  • [20160807][系统设计的三次迭代]
  • [Android]一个简单使用Handler做Timer的例子
  • [Codeforces1137D]Cooperative Game
  • [idea]关于idea开发乱码的配置
  • [iOS]中字体样式设置 API