Flask之数据库
SQL数据库
关系型数据库把数据存储在表中,表的列数是固定的,行数是可变的。
列定义表所表示的实体的数据属性,行定义各列对应的真实数据。
表中有个特殊的列,称为主键,它的值为表中各行的唯一标识符。
表中还可以有称为外键的列,引用同一个表或不同表中某行的主键
使用Flask-SQLALchemy管理数据库
在Flask-SQLALchemy中,数据库使用URL指定。
示例:配置数据库
from flask.ext.sqlalchemy import SQLALchemy
basedir=os.path.abspath(os.path.dirname(__file__))
#os.path.abspath()返回绝对地址,os.path.dirname(__file__)输出正在运行的脚本所在的完整路径
app=Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URL']=\'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
#配置对象中还有一个很有用的选项,即 SQLALCHEMY_COMMIT_ON_TEARDOWN 键,将其设为 True时,每次请求结束后都会自动提交数据库中的变动。
db=SQLALchemy(app) #db 对象是 SQLAlchemy 类的实例,表示程序使用的数据库
定义模型
Flask-SQLAlchemy 创建的数据库实例为模型提供了一个基类以及一系列辅助类和辅助函数。
示例:定义Role和User模型
class Role(db.Model):
__tablename__='roles'
id=db.column(db.interger,primary_key=True) #primary_key用来设置该列为主键
name=db.column(db.String(64),unique=True) #unique表示这列不能出现重复的数据
#db.Column的一个参数用来设置该列的数据类型
def __repr__(self):
return '' % self.username # __repr()__ 方法,返回一个具有可读性的字符串表示模型,可在调试和测试时使用。
class User(db.Model):
__tablename__='users'
id=db.Column(db.Integer,primary_key=True)
username=db.Column(db.String(64),unique=True,index=True)
def __repr__(self):
return '' % self.username
关系
关系型数据库使用关系把不同表中的行联系起来
示例:关系
class Role(db.Model):
#...
users=db.relationship('User',backref='role')
0.添加到Role模型中的users属性代表这个关系的面向对象视角。对于一个Role类的实例,其users属性将返回与角色相关联的用户组成的列表。
1.db.Relationship()第一个参数表明这个关系的另一端是哪个模型(类)。如果模型类尚未定义,可使用字符串形式指定。
2.db.Relationship()第二个参数backref,将向User类中添加一个role属性,从而定义反向关系。这一属性可替代role_id访问Role模型,此时获取的是模型对象,而不是外键的值。
class User(db.Model):
#...
role_id=db.Column(db.integer,db.ForeignKey('roles.id'))
#添加到 User 模型中的 role_id 列被定义为外键,就是这个外键建立起了关系。传给 db.ForeignKey() 的参数 'roles.id' 表明,这列的值是 roles 表中行的 id 值。
数据库操作
创建,插入,修改,删除,查询行
#创建
db.creat_all() #如果你查看程序目录,会发现新建了一个名为 data.sqlite 的文件
#插入行
from hello import Role,User
admin_role=Role(name='Admin')
mod_role=Role(name='Moderator')
user_role=Role(name='User')
user_john=User(username='John',role=admin_role)
user_susan=User(username='susan',role=user_role)
user_david=User(username='david',role=user_role)
#这些新建对象的 id属性并没有明确设定,因为主键是由 Flask-SQLAlchemy 管理的。现在这些对象只存在于Python 中,还未写入数据库。因此 id 尚未赋值
#通过数据库会话(db.session)管理对数据库所做的改动,数据库会话也称为*事务*
db.session.add(admin_role)
db.session.add(mod_role)
db.session.add(user_role)
...
#或者简写成
db.session.add_all([admin_role,mod_role,user_role,user_john,user_susan,user_david])
#调用commit()方法提交会话,把对象写入数据库
db.session.commit()
#修改行
admin_role.name='Administrator'
db.session.add(admin_role)
db.session.commit()
#删除行
db.session.delete(mod_role)
db.session.commit()
#查询行
Role.query.all()
User.query.all()
#使用过滤器配置query对象进行进行更精确的查询
User.query.filter_by(role=user_role).all()
#动态关系
class Role(db.Model):
#...
users=db.realationship('User',backref='role',lazy='dynamic')
在视图函数中操作数据库
示例:把用户输入的名字写入数据库
@app.route('/',methods=['GET','POST'])
def index():
form=NameForm()
if form.validate_on_submit():
user=User.query.fliter_by(username=form.name.data).first()
if user is None:
user=User(username=form.name.data)
db.session.add(user)
session['known']=False
else:
session['known']=True
session['name']=form.name.data
from.name.data=''
return redirect(url_for('index'))
return render_template('index.html',form=form,name=session.get('name'),known=session.get('knwon',Flase))
为了避免每次启动shell会话都要导入数据库实例和模型,为shell命令添加一个上下文
from flask.ext.script import Shell
def make_shell_context():
return dict(app=app,db=db,User=User.Role=Role)
manger.add_command('shell',Shell(make_context=make_shell_context))