( 上接Flask 框架学习(二) )
SQLAlchemy文档
Flask在可使用的数据库包上没有限制,所以可以使用MySQL、Postgres、SQLite、Redis、MongoDB或者CouchDB等等任意一个。
这里要引入一个概念。
ORM(对象关系映射,Object Relational Mapping)
是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。
听着就感觉很蛋疼,我们即将使用的Flask-SQLAlchemy扩展就是一个已经封装了关系对象映射(ORM)的一个插件。
而ORMs允许数据库程序用对象的方式替代表和SQL语句。面向对象的操作被ORM转化为数据库命令。这样就意味着,不用sql语句,让Flask-SQLAlchemy为我们执行sql语句。
简单的说,就是如SQLAlchemy或MongoEngine让你像操作常规Python对象那样,而不是数据库实体表、文档或查询语句。
应该稍微明白一点了,在之后的例子中能够很快就明白的。
此处我们以链接Mysql为例,在我们使用数据库的时候,需要在Flask配置对象中的SQLALCHEMY_DATABASE_URI
键中进行配置。另一个有用的选项是SQLALCHEMY_COMMIT_ON_TEARDOWN
,可以设置为True来启用自动提交数据库更改在每个请求中。
下述为.py文件的配置部分:
from flask.ext.sqlalchemy import SQLAlchemy
from flask import Flask
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] ="mysql://root:@localhost/flask"
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True
db = SQLAlchemy(app)
在SQLALCHEMY_DATABASE_URI
键的配置时,规定使用url来确定数据库,几个常用数据库的配置URL如下:
hostname是指托管MySQL服务的服务器(本地localhost或是远程服务器)
database指出要使用的数据库名
username和 password是数据库用户凭证
我的URL配置是
mysql://root:@localhost/flask
即我使用的用户名是root,而且没有密码,然后连接本地服务器,使用了名为flask的数据库。
现在我们例子如下:
class temp1(db.model):
__tablename__='temp1'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), unique=True)
class temp2(db.Model):
__tablename__ = 'temp2'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), unique=True)
来解释下上面的代码,
- 上述两个类就是我们的两个表,在ORM的背景下,我们将两个temp1表和temp2表抽象成了两个类,或是说两个模型。
- _table_类变量定义数据库中表的名称,缺省的复制Flask-SQLAlchemy
会默认赋值,但是我们使用的时候肯定要自己起上表名的。
- 而其他的类变量则是db.Column
的实例,即表中的列名。而db.Column
的第一个参数就是列的数据类型。而在Flask-SQLAlchemy
中,原有的SQL类型对应的Flask-SQLAlchemy
列类型如下:
db.Column的其他参数大概如下,都是列的一些属性,了解SQL的应该能够直接看懂:
小技巧,类定义中可以重载一下repr函数,就我个人的习惯来说,我经常犯各种错误,而且自己找不出来,这个时候就需要动用到ide来调试,这时候重写repr函数的优势就显示出来了…….
通常来说,正常的SQL一般表之间会存在各式各样的关系,现在列出一个配置模型的完整的源码(sql_1.py):
from flask.ext.sqlalchemy import SQLAlchemy
from flask import Flask
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] ="mysql://root:@localhost/flask"
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True
db = SQLAlchemy(app)
class temp1(db.Model):
__tablename__='temp1'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), unique=True)
brackref = db.relationship('temp2', backref='temp')
def __repr__(self):
return '<name %r>' % self.name
class temp2(db.Model):
__tablename__ = 'temp2'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), unique=True)
tempfk=db.Column(db.Integer, db.ForeignKey('temp1.id'))
def __repr__(self):
return '<username %r>' % self.username
上述应该比较好理解,添加给temp2一个tempfk的外键,链接的是temp1中的id列,db.relationship()
的backref
参数通过给temp2表增加temp
属性来定义反向关系。这个属性可以替代role_id访问Role模型,是作为对象而不是外键。
PS:这里我们重写了repr函数,具体的用途在之后会说的。
有了配置文件,我们就可以进入数据库操作部分了。
这里的演示我们直接在cmd中进行,然后一边配置mysql客户端来检验。
直接调用
db.create_all()
就可以创建出数据表,
确实成功了。
另一个db.drop_all()
则是删除所有表,这里不做演示了。
下面是插入数据
但是执行完上述语句之后还没有将数据写入Mysql
只是存于Python中,而且它们对应的id值还没有分配。
修改数据库的操作由Flask-SQLAlchemy提供的db.session数据库会话来管理。准备写入到数据库中的对象必须添加到会话中:
或是更简单点的:
为了写对象到数据库,需要通过它的commit()方法来提交会话:
db.session.commit()
运行之后观察MYSQL,发现数据已经写入:
这里发现我们之前没有对id赋值但是它却有值,而且该字段是auto_increment
的,
如果我们没有显示赋值是会从0自增的,当然肯定也是可以显示赋值的。
如果要修改会话中存在的值,例如我们添加了一个
>>> from sql_1 import db,temp1,temp2
>>> test=temp1(name="1234",id=100)
>>> db.session.add(test)
>>> db.session.commit()
我们想把name字段改成4321
那么直接
>>> test.name="4321"
>>> db.session.commit()
接下来是删除行
>>> db.session.delete(test)
>>> db.session.commit()
然后是返回行
Flask-SQLAlchemy为每个模型类创建一个query对象。最基本的查询模型是返回对应的表的全部内容:
>>> from sql_1 import db,temp1,temp2
>>> temp1.query.all()
[<name u'4321'>, <name u'admin'>, <name u'user'>]
>>> temp2.query.all()
[<username u'admin'>, <username u'user'>]
大家看看这个query.all()函数返回值是不是很眼熟,这就是我们之前在sql_1.py里面重写的repr函数的结构啊。
使用过滤器可以配置查询对象去执行更具体的数据库搜索。在表一中找出name字段为’admin’的记录。
>>> temp1.query.filter_by(name="admin").all()
[<name u'admin'>]
对于给定的查询还可以检查SQLAlchemy生成的原生SQL查询,并将查询对象转换为一个字符串:
>>> str(temp1.query.filter_by(name="admin"))
'SELECT temp1.id AS temp1_id, temp1.name AS temp1_name \nFROM temp1 \nWHERE temp1.name = :name_1'
还有另外一种方式来查询,如果我们知道了用户的id,我们可以使用下面的方式查找用户信息:
>>> temp2.query.get(1)
<username u'admin'>
想更深入的学习,还是看原文档吧SQLAlchemy文档