Flask-SQLALchemy 是一个给你的应用添加 SQLALchemy 支持的 Flask 扩展。SQLALchemy 是Python语言的SQL工具包及对象关系映射(ORM)工具,使用MIT许可证发行,提供能兼容众多数据库(如 SQLite、MySQL、Postgres、Oracle、MS-SQL、SQLServer 和 Firebird)的企业级持久性模型。
一、为你的Flask应用加载Flask-SqlAlchemy扩展
Code example:
1 2 3 4 5 6 |
from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' db = SQLAlchemy(app) #这个就是你以后操作数据库的对象实例了 |
SQLALCHEMY_DATABASE_URI格式实例:
1 2 3 4 |
postgresql://scott:tiger@localhost/mydatabase mysql://scott:tiger@localhost/mydatabase oracle://scott:tiger@127.0.0.1:1521/sidname sqlite:////absolute/path/to/foo.db #注意:有3个斜杠+路径 |
二、建立数据库模型和初始化数据库
建立数据库模型:
Code example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import hashlib from app import db #在数据库模型文件中导入上面建立的db对象 class User(db.Model): id = db.Column(db.Integer, primary_key=True) # id username = db.Column(db.String(80), unique=True) email = db.Column(db.String(320), unique=True) password = db.Column(db.String(32), nullable=False) def __init__(self, username, email, password): self.username = username self.email = email self.password= hashlib.md5(password) #呵呵,这样在插入数据自动给密码哈希了! def __repr__(self): return "<User '{:s}'>".format(self.username) |
初始化数据库也特别简单,只需要调用 db.create_all() 函数就可以了。
Code example:
1 2 |
if __name__ == '__main__': db.create_all() |
三、插入数据
Code example:
1 2 3 4 |
u = User(username='peter', email='test@example.com<script cf-hash="f9e31" type="text/javascript"> /* <![CDATA[ */!function(){try{var t="currentScript"in document?document.currentScript:function(){for(var t=document.getElementsByTagName("script"),e=t.length;e--;)if(t[e].getAttribute("cf-hash"))return t[e]}();if(t&&t.previousSibling){var e,r,n,i,c=t.previousSibling,a=c.getAttribute("data-cfemail");if(a){for(e="",r=parseInt(a.substr(0,2),16),n=2;a.length-n;n+=2)i=parseInt(a.substr(n,2),16)^r,e+=String.fromCharCode(i);e=document.createTextNode(e),c.parentNode.replaceChild(e,c)}}}catch(u){}}();/* ]]> */</script>', password='123456') db.session.add(u) #插入数据 db.session.commit() #只有提交事务了,才可以获取(u.id)数据的ID值。 |
四、查询数据
用主键获取数据:
Code example:
1 2 |
User.query.get(1) <User u'admin'> |
通过一个精确参数进行反查:
Code example:
1 2 |
peter = User.query.filter_by(username='peter').first() #注意:精确查询函数query.filter_by(),是通过传递参数进行查询;其他增强型查询函数是query.filter(),通过传递表达式进行查询。 print(peter.id) #如果数据不存在则返回None |
模糊查询:
Code example:
1 2 |
User.query.filter(User.email.endswith('@example.com')).all() [<User u'admin'>, <User u'guest'>] |
逻辑非1:
Code example:
1 2 |
peter = User.query.filter(User.username != 'peter').first() print(peter.id) |
逻辑非2:
Code example:
1 2 3 |
from sqlalchemy import not_ peter = User.query.filter(not_(User.username=='peter')).first() print(peter.id) |
逻辑与:
Code example:
1 2 3 |
from sqlalchemy import and_ peter = User.query.filter(and_(User.username=='peter', User.email.endswith('@example.com'))).first() print(peter.id) |
逻辑或:
Code example:
1 2 3 |
from sqlalchemy import or_ peter = User.query.filter(or_(User.username != 'peter', User.email.endswith('@example.com'))).first() print(peter.id) |
六、查询数据加工
排序和限制函数可以跟在query或filter后面。
排序:
Code example:
1 2 |
User.query.order_by(User.username) #嘿嘿,你用哪个字段作为排序参考呢? [<User u'admin'>, <User u'guest'>, <User u'peter'>] |
限制返回的数目:
Code example:
1 2 |
User.query.limit(1).all() [<User u'admin'>] |
六、查询数据返回
返回查询到的第一个对象:
Code example:
1 2 |
r = User.query.first() print(r) |
返回所有查询到的对象:
Code example:
1 2 |
r = User.query.all() print(r) |
七、删除数据
Code example:
1 2 3 |
u = User.query.first() db.session.delete(u) #删除数据和插入数据一样简单,但必须是通过查询返回的对象。 db.session.commit() |
八、更新数据
Code example:
1 2 3 |
u = User.query.first() u.username = 'guest' #更新数据和变量赋值那么简单,但必须是通过查询返回的对象。 db.session.commit() |
SQLALchemy-查询篇
似乎ORM最难设计的部分是查询。特别是面向对象的查询,今天学习SQLAlchemy,发现SQLAlchemy的查询语法竟如此灵活,惊叹其如此强大的表达能力的同时也对Python也有了更深的认识。下面看一下我写的一些查询语句:
Python代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
#简单查询 #注意User是一个类对象,user_table是数据库中的表 print(session.query(User).all()) ---相当于SQL语句---> select * from user_table print(session.query(User.name,User.fullname.all())) ---相当于SQL语句---> select user_table.name,user_table.fullname from user_table print(session.query(User,user.name).all()) ---相当于SQL语句---> select user_table.name from user_table #条件查询 print (session.query(User).filter_by(name='user1).all()) ---相当于SQL语句---> select * from user_table where name = 'user1' print (session.query(User).filter(User.name == "user).all()) ---相当于SQL语句---> select * from user_table where user_table.name = user print (session.query(User).filter(User.name.like("user%")).all()) ---相当于SQL语句---> select * from user_table where user_table.name like user% #多条件查询 print (session.query(User).filter(and_(User.name.like("user),User.fullname.like("first%"))).all() ---相当于SQL语句---> select * from user_table where user_table.name like %user and user_table.fullname like first% print(session.query(User).filter(or_(User.name.like("user%),User.password != None)).all() ---相当于SQL语句---> select * from user_table where user_table.name = user% or user_table.password != none #sql过滤 print(session(User).filter("id>:id").params(id=1).all() ---相当于SQL语句---> select * from user_table where user_table.id > 1 #关联查询 print(session.query(User,Address).filter(User.id == Address.user_id).all() ---相当于SQL语句---> select * from user_table,address_table where user_table.id == address.user_id print (session.query(User).jion(User.address).all() ---相当于SQL语句---> ******************** print (session.query(User).outerjoin(User.address).all()) ******************* #聚合查询 print(session.query(User.name,func.count('*').label("user_count)).group_by(User.name).all()) ---相当于SQL语句---> select count(user_table.name) as user_count from user_table where group by(user_table.name) print(session.query(User.name,func.sum(User.id).label("user_id_sum")).group_by(User.name).all()) ---相当于SQL语句---> select user_table.name,sum(user_table.id) from user_table where group by(user_table.name) #子查询 stmt = session.query(Address.user_id,func.count('*').label("address_count").group by(Address.user_id).subquery() print (session.query(User,stmt.c.address_count).outjion((stmt,User.id == stmt.c.user_id.order_by(User_id).all() #exits print (session.query(User).filter(exists().where(Address.user_id == User.id))) print (session.query(User).filter(User.addresses.any())) |
Flask SQLAlchemy 表字段默认值
在网上查到的SQLAlchemy设置字段默认值的方法都是类似如下方法:
1 2 3 4 5 6 |
from sqlalchemy.sql.sqltypes import TIMESTAMP class Test(db.Model): id = db.Column(db.Integer, primary_key = True) name = db.Column(db.String(32)) create_date = db.Column(TIMESTAMP, default = datetime.datetime) |
但这种方法其实这种方法根本就没有在数据库里面设置默认值,只是使用了SQLAlchemy Model类提交数据时添加上去的值,并不适合需要取数据库所有服务器时间的场合。
后来,发现一种使用SQLAlchemy模型直接在数据库设置默认值的方法:
#mysql 日期设置默认值必须使用timestamp类型
from sqlalchemy.sql.sqltypes import TIMESTAMP
#func用来生成数据库函数代码,跟踪进源代码看一***释就明白了
from sqlalchemy.sql import func
1 2 3 4 |
class Test(db.Model): id = db.Column(db.Integer, primary_key = True) name = db.Column(db.String(32)) create_date = db.Column(TIMESTAMP, server_default = func.now()) #注意这里是server_default |
在SQLAlchemy中使用字符串查询及原生SQL语句
SQLAlchemy提供给我们非常丰富的数据库查询方法,比如下面的代码中我们可以直接将查询条件以字符串的方式传入filter方法:
1 2 3 4 |
#String parameters for user in session.query(User).filter("id<224").\ order_by('id').all(): print user.id,user.name |
其相当于执行了下面的SQL语句:
1 2 3 4 |
SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password FROM users WHERE id<224 ORDER BY id |
上面的例子中我们直接指定了id的值小于244,如果我们希望动态传入参数,可以使用name=:value的方式,即以一个冒号:作为参数变量的前缀,然后在params方法中给出具体的参数值:
点击(此处)折叠或打开
1 2 3 4 |
#Named parameters user_fred= session.query(User).filter("id<:value and name=:name").\ params(value=224,name='Fred').order_by(User.id).one() print user.id,user.name,user.fullname |
其相当于执行了下面的SQL语句:
1 2 3 |
SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password FROM users WHERE id<? and name=? ORDER BY users.id |
或者我们可以直接把完整的查询语句放入filter方法中:
1 2 3 4 5 |
<pre class="theme:coda-special-board lang:default decode:true " >#String based statement for user in session.query(User).from_statement( "select * from users where name=:name" ).params(name='ed').all(): print user.id,user.name,user.fullname</pre> |
我们甚至可以不使用映射类,直接在query方法中指定查询结果字段,然后在filter方法中写入SQL语句:
1 2 3 4 5 6 |
#Raw SQL for user in session.query("id","name","thenumber12").\ from_statement( "select id,name,12 as thenumber12 from users where name=:name" ).params(name='ed').all(): print user.id,user.name,user.thenumber12 |
其相当于执行以下的SQL语句:
1 2 |
select id,name,12 as thenumber12 from users where name=? 2011-12-16 13:11:22,619 INFO sqlalchemy.engine.base.Engine ('ed',) |
要注意的是,在使用原生字符串SQL查询的时候,如果涉及到嵌套查询,或者一个SQL中出现相同的表名的情况下,假如希望按照明某个表字段进行排序,那么必须明确给出,是按照哪个表的字段排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#Pros and Cons of literal SQL q=session.query(User.id,User.name) for user in q.order_by("name").all(): print user from sqlalchemy import func from sqlalchemy.orm import aliased ua=aliased(User) q=q.from_self(User.id,User.name,ua.name).filter(User.name<ua.name).\ filter(func.length(ua.name)!=func.length(User.name)) for user in q.order_by("name").all(): print user for user in q.order_by(ua.name).all(): print user for user in q.order_by(User.name).all(): print user |
上面的例子中,第一句直接用”name”来排序,但是SQLAlchemy不知道是应该用哪个User表的name排序,所以后面两个方法中,我们分别给出了明确的指示,其执行SQL语句如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
--statement 1 SELECT anon_1.users_id AS anon_1_users_id, anon_1.users_name AS anon_1_users_name, users_1.name AS users_1_name FROM (SELECT users.id AS users_id, users.name AS users_name FROM users) AS anon_1, users AS users_1 WHERE anon_1.users_name < users_1.name AND length(users_1.name) != length(anon_1.users_name) ORDER BY name --statement 2 SELECT anon_1.users_id AS anon_1_users_id, anon_1.users_name AS anon_1_users_name, users_1.name AS users_1_name FROM (SELECT users.id AS users_id, users.name AS users_name FROM users) AS anon_1, users AS users_1 WHERE anon_1.users_name < users_1.name AND length(users_1.name) != length(anon_1.users_name) ORDER BY users_1.name --statement 3 SELECT anon_1.users_id AS anon_1_users_id, anon_1.users_name AS anon_1_users_name, users_1.name AS users_1_name FROM (SELECT users.id AS users_id, users.name AS users_name FROM users) AS anon_1, users AS users_1 WHERE anon_1.users_name < users_1.name AND length(users_1.name) != length(anon_1.users_name) ORDER BY anon_1.users_name |
0 Comments