数据库分为SQL数据库(关系模型数据库)和NoSQL数据库(非关系模型数据库,主要为文档数据库和键值对数据库。)
SQL数据库高效紧凑的形式储存结构化数据,但花费精力在数据的一致性上。
NOSQL数据库不紧凑,但数据重复可以提升查询速度。
Flask不限制你使用何种数据库包,如MySQL,Postgres,SQLite,Redis,MongoDB,CouchDB等。
数据库抽象层代码包,如SQLAlchemy和MongoEngine,使用这些抽象包直接处理高等级的Python对象,而不用处理如表,文档或查询语言此类数据库实体。
使用Flask-SQLAlchemy管理数据库
(venv) $ pip install flask-sqlalchemy
import os
from flask import Flask, render_template, session, redirect, url_for, flash
from flask_script import Manager
from flask_bootstrap import Bootstrap
from flask_moment import Moment
from flask_wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required
from flask_sqlalchemy import SQLAlchemy ###从模块引入
basedir = os.path.abspath(os.path.dirname(__file__))
###获取程序文件根目录(去掉文件名本身如C:\Users\Geek Lee\Geek-Lee.github.io)
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
app.config['SQLALCHEMY_DATABASE_URI'] = \
'sqlite:///' + os.path.join(basedir, 'data.sqlite')
###程序使用的数据库URL必须保存在Flask配置对象的SQLALCHEMY_DATABASE_URI键中。
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
###SQLALCHEMY_COMMIT_ON_TEARDOWN键设为True,每次请求结束后自动提交到数据库中的变动。
manager = Manager(app)
bootstrap = Bootstrap(app)
moment = Moment(app)
db = SQLAlchemy(app)
###db对象是SQLAlchemy类的实例,表示程序使用的数据库,同时还获得了Flask-SQLAlchemy提供的所有的功能。
class Role(db.Model): ###定义模型
__tablename__ = 'roles' ###表名
id = db.Column(db.Integer, primary_key=True)###属性代表列
name = db.Column(db.String(64), unique=True)
users = db.relationship('User', backref='role',lazy='dynamic')
def __repr__(self):
return '<Role %r>' % 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 %r>' % self.username
class NameForm(Form):
name = StringField('What is your name?', validators=[Required()])
submit = SubmitField('Submit')
@app.route('/', methods=['GET', 'POST'])
def index():
form = NameForm()
if form.validate_on_submit():
old_name = session.get('name')
if old_name is not None and old_name != form.name.data:
flash('Looks like you have changed your name!')
session['name'] = form.name.data
return redirect(url_for('index'))
return render_template('index.html',
form = form, name=session.get('name'))
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'),404
@app.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'),500
if __name__ == '__main__':
manager.run()
具体研究两表之间的关系和外键
class Role(db.Model): ###定义模型
__tablename__ = 'roles' ###表名
id = db.Column(db.Integer, primary_key=True)###属性代表列
name = db.Column(db.String(64), unique=True)
users = db.relationship('User', backref='role',lazy='dynamic')
def __repr__(self):
return '<Role %r>' % 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 %r>' % self.username
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
重点解释
User模型中的 role_id列被定义为外键,就是这个外键建立起与其他模型的联系。
db.ForeignKey('roles.id')
代表了role_id的值就是roles表中行id的值
(**roles.id解释**roles是Role类的表名,id是Role类的属性,用roles.id建立与User的属性role_id的联系)
外键放在多的地方,相当于标签作用,代表这个用户(多个)属于什么角色(一个)。ps:好多用户都是一个角色。
users = db.relationship('User', backref='role',lazy='dynamic'
)重点解释
添加到Role模型中的users属性代表这个关系的面向对象视角。(不懂)
对于一个Role类的实例(如user_role),其users属性将返回与角色相关联的用户组成的列表。
语句解释如下:
建立了几个Role类实例,如admin_role,mod_role,user_role。
>>>from hello import Role, User
>>>admin_role=Role(name='Admin')
>>>mod_role=Role(name='Moderate')
>>>user_role=Role(name='User')
###注意这个里面的User不是User类,仅仅是表示name属性为User角色(name叫User的角色)
提交等中间环节省略。。。
>>>users = user_role.users
###第一个users是变量,user_role是Role类实例,第二个users是类的属性(数据库中的列概念)
>>>users
[<User u'susan'>,<User u'david'>]
>>>users[0].role
<Role u'User'>
以上步奏为建好Role类实例,加上users属性返回是这个角色(角色名Admin,Moderate,User)的user用户列表。
db.realationship()的backref参数向User模型中添加一个role属性,从而定义反向关系。这一属性可替代role_id访问Role模型,此时获取的 是模型对象,而不是外键的值。
解释语句:
(一)db.realationship()的backref参数向User模型中添加一个role属性
(role这个属性名字可以随便起,只要通俗易懂就行了。)
注意哦注意哦,是向User模型添加哦,是向User模型添加哦,是向User模型添加哦。虽然他在Role模型里。但是是可以把它当成User的属性用的。
在Role类中,是User类的属性,访问Role模型,获取的是Role模型对象。
用法如:User实例.role
#接上回创建的Role类实例
>>>users[0].role ###user变量为列表
<Role u'User'>
(二)这一属性可替代User的属性role_id访问Role模型,但是此时获取的是模型对象,而不是外键的值。
如上获取了<Role u'User'>