参考1:http://blog.csdn.net/happy_bigqiang/article/details/50935935
参考2:http://www.jb51.net/article/86606.htm
一、前言介绍
运行环境:
Centos6.5,python3.4
预备知识:
- roles表中为id列添加主键属性,另一张表users为role_id列添加外键属性,这样主键就对应上外键,产生了一旦在roles表中修改完角色名(roles表中的name列的行值),所有通过role_id引用这个角色的用户都能立即看到更新的关系,故取名关系型数据库。
- NoSQL数据库一般使用集合代替表,使用文档代替记录;使用NoSQL数据库的好处是,数据重复可以提升查询速度。
- 操作数据库有几种方法:
- 可以在数据库命令行写SQL语句,即底层操作数据库。
- 在python中可以用一些数据库驱动比如MySQL-python驱动来操作数据库,驱动对底层繁琐命令进行了封装。
- 在flask中使用SQLAlchemy数据库框架对数据库驱动进一步封装,进一步简化命令。因此SQLAlchemy不是数据库,而是对数据库进行操作的一种框架。
数据库管理:
- 配置数据库;
- 定义数据库模型,并对数据库中的表建立关系;
- 数据库的基本操作(命令行中操作):
创建表,插入行,修改行,删除行,查询行
- 视图函数中操作数据库;
- 集成python shell ;
- flask-migrate 实现数据库迁移;
二、具体步骤
安装flask-sqlalchemy、pymysql模块
pip install flask-sqlalchemy pymysql
测试链接数据库
直接上代码
使用Flask-SQLAlchemy管理数据库
Flask-SQLAlchemy是一个Flask扩展,它简化了在Flask应用程序中对SQLAlchemy的使用。SQLAlchemy是一个强大的关系数据库框架,支持一些数据库后端。提供高级的ORM和底层访问数据库的本地SQL功能。
# coding:utf-8
from flask.ext.sqlalchemy import SQLAlchemy
from flask import Flask
'''配置数据库'''
app = Flask(__name__)
app.config['SECRET_KEY'] ='hard to guess'
# 这里登陆的是root用户,要填上自己的密码,MySQL的默认端口是3306,填上之前创建的数据库名jianshu,连接方式参考 \
# http://docs.sqlalchemy.org/en/latest/dialects/mysql.html
app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://jianshu:jianshu@127.0.0.1:3306/jianshu'
#设置这一项是每次请求结束后都会自动提交数据库中的变动
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True
#实例化
db = SQLAlchemy(app)
应用程序数据库URL必须在Flask配置对象中的SQLALCHEMY_DATABASE_URI键中进行配置。另一个有用的选项是SQLALCHEMY_COMMIT_ON_TEARDOWN,可以设置为True来启用自动提交数据库更改在每个请求中。查阅Flask-SQLAlchemy文档获取更多其他配置选项。
由SQLAlchemy实例化的db对象表示数据库且提供访问Flask-SQLAlchemy的所有功能。
模型定义
模型是指由应用程序使用的持久化实体。在ORM的背景下,一个模型通常是一个带有属性的Python类,其属性与数据库表的列相匹配对应。Flask-SQLAlchemy数据库实例提供了一个基类以及一组辅助类和函数用于定义它的结构。
'''定义模型,建立关系'''
class Role(db.Model):
# 定义表名
__tablename__ = 'roles'
# 定义列对象
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
user = db.relationship('User', backref='role')
#repr()方法显示一个可读字符串,虽然不是完全必要,不过用于调试和测试还是很不错的。
def __repr__(self):
return '<Role {}> '.format(self.name)
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, index=True)
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
def __repr__(self):
return '<User {}>'.format(self.username)
__tablename__
类变量定义数据库中表的名称。如果tablename缺省Flask-SQLAlchemy会指定默认的表名,但是这些缺省名称不遵守使用复数命名的约定,所以最好是显式命名表名。其余的变量是模型的属性,被定义为db.Column类的实例。
传给db.Column构造函数的第一个参数是数据库列的类型也就是模型属性的数据类型。图下列出一些可用的列的类型,也是用于模型中的Python类型
db.Column剩余的参数为每个属性指定了配置选项。表格5-3列出一些可用的选项。
关系
关系数据库通过使用关系在不同的表中建立连接。关系图表达了用户和用户角色之间的简单关系。这个角色和用户是一对多关系,因为一个角色可以从属于多个用户,而一个用户只能拥有一个角色。
下面的模型类展示了中表达的一对多关系。
class Role(db.Model):
# ...
users = db.relationship('User', backref='role')
class User(db.Model):
# ...
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
关系通过使用外键来连接两行。添加给User模型的role_id列被定义为外键,且建立关系。db.ForeignKey()的参数roles.id指定的列应该理解为在roles表的行中持有id值的列。
添加到Role模型的users属性表现了关系的面向对象的观点。给定Role类的实例,users属性会返回一组连接到该角色的用户。指定给db.relationship()的第一个参数表明模型中关系的另一边。如果类还未定义,这个模型可以作为字符串提供。
注意:之前在segmentdefault中遇到的问题,后来粗略阅读了SQLAlchemy的源码。ForeignKey类的column接收三种类型的参数,一种是“模型名.属性名”;一种是“表名.列名”,最后一种没看明白,下次试着用一下。
db.relationship()的backref参数通过给User模型增加role属性来定义反向关系。这个属性可以替代role_id访问Role模型,是作为对象而不是外键。
大多数情况下db.relationship()可以定位自己的外键关系,但是有时候不能确定哪个列被用作外键。例如,如果User模型有两个或更多列被定义为Role的外键,SQLAlchemy将不知道使用两个中的哪一个。每当外键配置模棱两可的时候,就必须使用额外参数db.relationship()。下标列出一些常用配置选项用于定义关系:
数据库操作
'''进行数据库操作'''
if __name__ == '__main__':
# 删除旧的表
db.drop_all()
db.create_all()
# 插入数据
admin_role = Role(name='Admin')
mod_role = Role(name='Moderator')
user_role = Role(name='User')
# role属性也可使用,虽然他不是真正的数据库列,但却是一对多关系的高级表示
user_john = User(username='john', role=admin_role)
user_susan = User(username='susan', role=user_role)
user_david = User(username='david', role=user_role)
# 准备把对象写入数据库之前,先要将其添加到会话中,数据库会话db.session和Flask session对象没有关系,数据库会话也称事物
db.session.add_all([admin_role, mod_role, user_role, user_john, user_susan, user_david])
# 提交会话到数据库
db.session.commit()
# 修改roles名
admin_role.name = 'Administrator'
db.session.add(admin_role)
db.session.commit()
# 删除数据库会话,从数据库中删除“Moderator”角色
db.session.delete(mod_role)
db.session.commit()
# 注意删除,和插入更新一样,都是在数据库会话提交后执行
#查询
print(user_role)
print(User.query.filter_by(role=user_role).all())
过滤器如filter_by()通过query对象来调用,且返回经过提炼后的query。多个过滤器可以依次调用直到需要的查询配置结束为止。
在需要的过滤器已经全部运用于query后,调用all()会触发query执行并返回一组结果,但是除了all()以外还有其他方式可以触发执行。
更多SQLAlchemy方法: flask-sqlalchemy 简单笔记
执行
> python app.py
<Role User>
[<User susan>, <User david>]
查看数据库,可以看到数据已经写入了