Python SQLAlchemy ORM示例
SQLAlchemy的是Python的SQL工具包和对象关系映射,给应用程序开发者提供SQL的强大功能和灵活性。 安装
pip install mysql-python
pip install sqlalchemy 初始化
SQLAlchemy ORM提供了一个连接数据库表和用户自定义Python类的方法。 在使用ORM时,我们要初始化一些基本的变量。 定义映射基类
类的映射(Mapping)使用已经在基类中定义的声明式系统,declarative_base类维持了一个从类到表的关系,通常一个应用使用一个base实例,所有实体类都应该继承此类对象。
我们的应用在一般导入的模块中将只有一个这个基类的实例,使用declarative_base()创建这个基类的实例。 from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base() 创建engine
ORM操作数据库的句柄就是Session。在创建session前,我们先创建一个engine实例。 from sqlalchemy import create_engine
mysql_engine = create_engine("mysql://root:1@127.0.0.1/cms?charset=utf8",
pool_size=1,
max_overflow=10,
echo=False,
encoding='utf-8',
pool_recycle=20000
) 创建session
当我们启动我们的应用时,在create_engine()的同时,我们定义了一个Session类将作为一个创建Session实例的工厂。 from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
1
2
把上面三部整理到一个base.py文件中,方便后续调用: # coding: utf-8
"""
base.py
Usage: 使用sqlalchemy中的base类型
"""
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() mysql_engine = create_engine("mysql://root:1@127.0.0.1/cms?charset=utf8",
pool_size=1,
max_overflow=10,
echo=False,
encoding='utf-8',
pool_recycle=20000
) Session = sessionmaker(bind=mysql_engine) 实体类(model)
我们基于base.py定义了一个User类。sqlalchemy 就是把Base子类转变为数据库表,定义好User类后,会生成Table和mapper(),分别通过User.table 和User.mapper返回这两个对象。 # coding: utf-8
import logging
from sqlalchemy import *
from base import Base
from base import Session class User(Base):
__tablename__ = 'user'
__table_args__ = {'mysql_engine': 'InnoDB', 'mysql_charset': 'utf8'} id = Column(BigInteger, primary_key=True)
name = Column(String(100), nullable=False)
password = Column(String(100), nullable=False) @classmethod
def to_dict(cls, row):
if not row:
return None d = {'id': row.id,
'name': row.name,
'password': row.password
} return d @classmethod
def get(cls, session, user_id):
row = session.query(cls).filter(cls.id == user_id).first() return cls.to_dict(row) @classmethod
def update(cls, session, user_id, name, password):
try:
session.query(cls.id == user_id).update({cls.name: name, cls.password: password})
session.commit()
return True
except Exception, e:
logging.error(e)
return False @classmethod
def add(cls, session, name, password):
user = cls(name=name,
password=password) session.add(user)
try:
session.commit()
return user.id
except Exception, e:
logging.error(e)
return None @classmethod
def remove(cls, session, user_id):
try:
session.query(cls.id == user_id).delete()
session.commit()
return True
except Exception, e:
logging.error(e)
return False if __name__ == '__main__':
session = Session() user_id = User.add(session, name='test', password='123')
print User.get(session, user_id=user_id) print User.update(session, user_id, name='update', password='456')
print User.get(session, user_id=user_id) print User.remove(session, user_id=user_id)
print User.get(session, user_id=user_id) session.close() 执行结果: {'password': u'123', 'id': 3L, 'name': u'test'}
True
{'password': u'456', 'id': 3L, 'name': u'update'}
True
None
1
2
3
4
5
在这个model中基于session,实现了对数据增删查改的方法。 增删查改
add
user = cls(name=name,
password=password) session.add(user)
1
2
3
4
在调用add时,user实例是待定的(pending),不执行任何SQL,不会触发insert,因此也不代表数据库中的一行数据。
当使用一个flush过程时,Session将执行SQL来持久化user。 对象状态 对象实例有四种状态,分别是:
1. Transient(瞬时的):这个状态的对象还不在session中,也不会保存到数据库中,主键为None(不是绝对的,如果Persistent对象rollback后虽然主键id有值,但还是Transient状态的)。
2. Pending(挂起的):调用session.add()后,Transient对象就会变成Pending,这个时候它还是不会保存到数据库中,只有等到触发了flush动作才会存在数据库,比如query操作就可以出发flush。同样这个时候的实例的主键一样为None
3. Persistent(持久的):session中,数据库中都有对应的一条记录存在,主键有值了。
4. Detached(游离的):数据库中有记录,但是session中不存在,对这个状态的对象进行操作时,不会触发任何SQL语句。 Session是真正与数据库通信的handler,我们告诉Session我们想要将所有的改变(add,delete,update)存入到数据库,提交事务;然后通过commit()来执行。 query
查询 Query对象通过Session.query获取,query接收类或属性参数,以及多个类。 row = session.query(cls).filter(and_(cls.name == name, cls.password == password)).first()
1
执行query时,session返回同一行(对象)就是我们刚刚在session内部的类的字典持久化的对象,所以我们事实上获得的就是我们加入Session中的实例。
Session 使用 connection发送query,把返回的result row 填充到一个Python object中,该对象同时还会保存在Session中,Session内部有一个叫 Identity Map的数据结构,为每一个对象维持了唯一的副本。 filter()方法通常接收的是Python操作符,而filter_by()方法使用关键字参数。filter可以接收更加灵活的SQL表达式结构,一般情况下,基本够用了。 查询返回结果有多种:
1. query.all(),all()返回列表
2. query.first(),返回第一个元素
3. query.one(),有且只有一个元素时才正确返回。 delete
session.query(cls.id == user_id).delete()
1
update
session.query(cls.id == user_id).update({cls.name: name, cls.password: password})
1
小结
本文记录了使用SQLAlchemy实现常见的CRUD操作,后续会继续记录使用中踩到的坑和一些使用技巧。
SQLAlchemy 在构建在 WSGI 规范上的Python Web 框架中得到了广泛应用,在我司的生产环境中久经考验,配合Flask和Tornado一起开发效率极高。
https://blog.csdn.net/dutsoft/article/details/74842722
Python SQLAlchemy ORM示例的更多相关文章
- Python sqlalchemy orm 多对多外键关联
多对多外键关联 注:使用三张表进行对应关联 实现代码: # 创建3个表 配置外键关联 # 调用Column创建字段 加类型 from sqlalchemy import Table, Column, ...
- Python sqlalchemy orm 常用操作
增add # 创建表1 # 注:高级封装 import sqlalchemy # 调用链接数据库 from sqlalchemy import create_engine # 调用基类Base fro ...
- Python sqlalchemy orm 外键关联
创建外键关联 并通过relationship 互相调用 如图: 实现代码: import sqlalchemy # 调用链接数据库 from sqlalchemy import create_engi ...
- Python sqlalchemy orm 多外键关联
多外键关联 注:在两个表之间进行多外键链接 如图: 案例: # 创建两张表并添加外键主键 # 调用Column创建字段 加类型 from sqlalchemy import Integer, For ...
- Python SQLAlchemy --3
本文為 Python SQLAlchemy ORM 一系列教學文: 刪除 學會如何查詢之後,就能夠進行後續的刪除.更新等操作. 同樣地,以幾個範例做為學習的捷徑. 123456789 user_1 = ...
- Python SQLAlchemy --2
本文為 Python SQLAlchemy ORM 一系列教學文: 接下來會更深入地探討查詢的使用. 查詢的基本使用法為 session.query(Mapped Class),其後可加 .group ...
- Python SQLAlchemy --1
本文為 Python SQLAlchemy ORM 一系列教學文: SQLAlchemy 大概是目前 Python 最完整的資料庫操作的套件了,不過最令人垢病的是它的文件真的很難閱讀,如果不搭配個實例 ...
- python的ORM框架SQLAlchemy
本节内容 ORM介绍 sqlalchemy安装 sqlalchemy基本使用 多外键关联 多对多关系 表结构设计作业 一.ORM介绍 如果写程序用pymysql和程序交互,那是不是要写原生sql语句 ...
- python 学习笔记十一 SQLALchemy ORM(进阶篇)
SqlAlchemy ORM SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据A ...
随机推荐
- AndroidUI组件之ActionBar
有一段时间没有写博文了,发现自己的博文的完整度不是非常好.就拿AndroidUI组件这一块.一直没有更新完.我会尽快更新.好了.不多说了,今天来看一下ActionBar. 依照以往的作风.知识点都以代 ...
- COCOS学习笔记--Button类及其相关控件属性
一.Button介绍 Button就是button.Cocos中提供了Button类对button进行相关的操作.我们看一下Button类继承关系图: 能够看到.Button是继承自Widget类,W ...
- 【BZOJ 3790】 神奇项链
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3790 [算法] manacher + 贪心 [代码] #include<bit ...
- bzoj 4481 [ Jsoi 2015 ] 非诚勿扰 —— 期望
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4481 太弱了这种题都要看半天TJ...:https://blog.csdn.net/chai ...
- 杂项-Java:标签库
ylbtech-杂项-Java:标签库 1.返回顶部 1. JSP标签库,也称自定义标签库,可看成是一种通过JavaBean生成基于XML的脚本的方法.从概念上讲,标签就是很简单而且可重用的代码结构. ...
- 84. ExtJS下页面显示中文乱码问题
转自:https://blog.csdn.net/wenminhao/article/details/51198981 最近在学校extjs是,使用js脚本显示中文在html页面中时,中午出现了乱码的 ...
- form内部的button_to不submit
创建: 2017/09/12 更新: 2018/03/17 修正因为博客迁移造成的格式问题 官方文档 http://railsdoc.com/references/button_to 参考文档 htt ...
- Labeling Balls(拓扑)
http://poj.org/problem?id=3687 看题意看了半天没看懂怎么回事,看完Discuss彻底凌乱了..后来看了题解才懂,就是逆向建图+拓扑排序,建图时要判重边. #include ...
- git clone 出现错误
看了好多资料终于搞定了git 中clone命令报错这个问题,废话不多说直接上步骤希望对大家有帮助. 1 删除.ssh文件夹(直接搜索该文件夹)下的known_hosts(手动删除即可,不需要git ...
- Run as ant build每次都执行两次-问题解决
在Eclipse里面,运行ant,整个测试流程总是执行两遍,其几天试了下在DOS命令行直接调用ant, 结果发现只执行了一次,并且内存消耗好像也没那么大了,估计是eclipse自己的问题.问题解决了, ...