flask插件之Flask-WTF表单、flask_SQLAlchemy数据库的使用

flask插件之Flask-WTF表单、flask_SQLAlchemy数据库的使用

  • 先pip安装
  • 需要csrf保护
  • 创建表单
  • 创建用户模型
    • 用户模型的一对多关系(也就是外键)
  • 用flask_SQLAlchemy来创建数据库表(只有一步,伪迁移)
    • 然后在视图函数注册进数据库:
  • flask_SQLAlchemy生成的数据库操作对象的增删改查
    • 查询
    • 删和改
  • 用flask-migrate数据库迁移(真迁移)
    • 实际操作顺序
    • 配置
    • 迁移过程
    • 返回以前的版本

环境:python3.5,Flask1.0.3
查看官方文档:http://www.pythondoc.com/flask-wtf/form.html

先pip安装

flask_wtf是flask框架的表单验证模块,可以很方便生成表单,也可以当做json数据交互的验证工具,支持热插拔。

pip install flask-WTF

需要csrf保护

设置app.secret_key即可

app.secret_key = 'qwertyudfghjkl;xcvbn'

最后,我们需要在响应的html模板的Form表单中加上如下语句:

{{form.csrf_token}}

或者:

{{form.hidden_tag()}}

其中的form是views.py中对应处理函数传递过来的Form对象名称,根据具体情况会有所变化。通过上面的配置,我们就启动了CSRF保护。

创建表单

通常是设置为一个表单类,然后在视图函数初始化为表单对象:
注意这个写完id也给你写了,默认等于name等于label

class RegisterForm(Form):
    # 用户名,分别验证为必须字段,长度,以及额外设置属性
    username = StringField('用户名:', [validators.data_required, validators.length(min=3, max=20)], render_kw={'placeholder': '输入用户名'})
    # email = StringField('Email Address', [validators.Length(min=6, max=35)])
    # 密码和确认密码,需要验证是否一致,注意字段名不能填错
    password = PasswordField('密码:', [
        validators.DataRequired(),
        validators.EqualTo('confirm', message='密码必须一致')
    ])
    confirm = PasswordField('确认密码:')
    # 这个是是否接收条件
    # accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])
    # 提交按钮
    submit = SubmitField('注册')

然后在视图函数初始化并返回:

@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm(request.form)
    if request.method == 'POST' and form.validate():
    	# 这里准备些注册数据库
        return 'register success'
        
    return render_template('register.html', form=form)

最后是html内容显示,在body里写即可:

<form method="post" enctype="multipart/form-data">
{#    {{ form.hidden_tag() }}#}
    {{ form.csrf_token }}

    {{ form.username.label }}{{ form.username }}<br>
    {{ form.password.label }}{{ form.password }}<br>
    {{ form.confirm.label }}{{ form.confirm }}<br>
    {{ form.submit }}<br>

form>

创建用户模型

在mysql准备一个数据库例如名为flask的数据库
然后安装关系扩展和mysqldb:

pip install flask-sqlalchemy
pip install flask-mysqldb

先用app注册数据库地址:

# 用于连接数据库的uri地址,账户密码
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/flask'

然后创建用户模型:

from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# 创建一个管理数据库对象,需要和应用产生联系
db = SQLAlchemy(app)


# 创建用户类
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True)
    password = db.Column(db.String(20))
    is_delete = db.Column(db.Boolean, default=False)
    email = db.Column(db.String(30), nullable=True)

用户模型的一对多关系(也就是外键)

创建一个角色类,比如说用户有用户等级,vip什么的,也就是角色一对多用户

# 创建角色类,一个用户只有一个角色
class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), unique=True)
    # backref是反向引用,lazy是对反向解析的操作,'dynamic'是默认的不调用不查找
    users = db.relationship('User', backref='roles', lazy='dynamic')
    
    def __repr__(self):
        return self.name

user模型添加外键:

# 外键
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

对于Flask中外键的解释:

  • Role.users = db.relationship(‘User’, backref=‘role’) : 代表 外键关系的
    面向对象视角. 对于一个 Role 类的实例, 其 users 属性将返回与角色相关联的用户组成的列表.
  • db.relationship() 第一个参数表示这个关系的另一端是哪个模型。
  • backref 参数, 向 User 模型添加了一个 role 数据属性, 从而定义反向关系. 这一属性可替代 role_id 访问
    Role 模型, 此时获取的是模型对象, 而不是外键的值

用flask_SQLAlchemy来创建数据库表(只有一步,伪迁移)

这个db.create_all()只需要创建一次,之后备注掉

# 创建一个管理数据库对象,需要和应用产生联系
db = SQLAlchemy(app)
if __name__ == '__main__':
    # 删除全部和创建
    # db.drop_all()
    # db.create_all()
    app.run()

然后在视图函数注册进数据库:

@app.route('/register', methods=['GET', 'POST'])
def register():
    reg_form = RegisterForm()

    if request.method == 'POST':
        if reg_form.validate_on_submit():
            # 注册进数据库
            print(reg_form.validate_on_submit())
            user = User(username=reg_form.username.data, password=reg_form.password.data)
            db.session.add(user)  # 插入一条
            # db.session.add_all([..., ...])  #  插入多条
            # commit真正提交到数据库
            db.session.commit()
            # flash('Thanks for registering')
            return 'register success'
            # return redirect(url_for('login'))
        else:
            print('err', reg_form.validate_on_submit())
            return '验证不成'
    return render_template('register.html', form=reg_form)

flask_SQLAlchemy生成的数据库操作对象的增删改查

查询

filter_by()是精确查找,模糊查找是filter()

# 创建一个管理数据库对象,需要和应用产生联系
db = SQLAlchemy(app)
# 查询db.Model类生成的模型,根据某条件,返回的是一个列表
User.query.filter_by(username='xx').all()
User.query.first()  # 查找第一个
User.query.all()  # 查找全部
# 查找以什么开头的数据,没有all()则是返回一个对象
User.query.filter(User.username.startswith('wo')).all()
User.query.filter(User.username.endswith('hui'))  # 查找以什么结尾

查找id=1的三种方法,返回的都是列表,差找不到为空

User.query.filter_by(id=1).all()
User.query.filter(User.id==1).all()
# get是只能查找主键,如果查找不到没有返回内容
User.query.get(1)

与或非条件查询,需要导包

# 非条件
User.query.filter(User.username!='woshishui').all()
# 这个需要导包
from sqlalchemy import not_
User.query.filter(not_(User.username=='woshishui')).all()

# 与条件,里面是多个条件用逗号分隔,必须都成立否则返回为空
from sqlalchemy import and_
User.query.filter(and_(User.username.endswith('hui'), User.is_delete==0)).all()

# 或条件,用法同上面导入or_即可

删和改

删除需要根据id删除

from testdb import User, db
user = User.query.get(2)
db.session.delete(user)
db.session.commit()

改直接修改然后commit即可:

user = User.query.get(1)
user.email = '[email protected]'
db.session.commit()

用flask-migrate数据库迁移(真迁移)

  • 在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库。最直接的方式就是删除旧表,但这样会丢失数据。
  • 更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化,然后把变动应用到数据库中。
  • 在Flask中可以使用Flask-Migrate扩展,来实现数据迁移。并且集成到Flask-Script中,所有操作通过命令就能完成。
  • 为了导出数据库迁移命令,Flask-Migrate提供了一个MigrateCommand类,可以附加到flask-script的manager对象上。

实际操作顺序

  • 1.python 文件 db init
  • 2.python 文件 db migrate -m"版本名(注释)"
  • 3.python 文件 db upgrade 然后观察表结构
  • 4.根据需求修改模型
  • 5.python 文件 db migrate -m"版本名(注释)"
  • 6.python 文件 db upgrade 然后观察表结构
  • 7.若返回版本,则利用 python 文件 db history查看版本号
  • 8.python 文件 db downgrade(upgrade) 版本号

配置

先pip安装:

pip install flask-migrate
pip install flask_script

flask_script的Manager使用

  • 创建一个Manager对象,参数是Flask实例
  • 然后启动服务器用 python xx.py runserver -p 5000 后面是端口

然后是对应的py文件:

from flask import Flask, render_template, request
from wtforms import Form, BooleanField, StringField, PasswordField, validators, SubmitField
from flask_wtf import FlaskForm
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate, MigrateCommand
from flask_script import Shell, Manager

app = Flask(__name__)
manager = Manager(app)

app.secret_key = 'qwertyudfghjkl;xcvbn'
# 用于连接数据库的uri地址,账户密码
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/flask'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['DEBUG'] = True


# 创建一个管理数据库对象(句柄)
db = SQLAlchemy(app)
# 这个是迁移实例,第一个参数是Flask的实例,第二个参数是Sqlalchemy数据库实例
migrate = Migrate(app, db)
# manager是Flask-Script的实例,这条语句在flask-Script中添加一个db命令,这个命令和上面创建的db操作句柄无关
manager.add_command('db', MigrateCommand)


# 创建用户类
class User(db.Model):
    # 定义表名
    __table__ = 'users'
    # 定义列对象
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True)
    password = db.Column(db.String(20))
    is_delete = db.Column(db.Boolean, default=False)
    email = db.Column(db.String(30), nullable=True)
    
    # 这个是返回可读字符串
    def __repr__(self):
        return 'User:'.format(self.username)


class RegisterForm(FlaskForm):
    # 用户名,分别验证为必须字段,长度,以及额外设置属性
    username = StringField('用户名:', [validators.data_required(), validators.length(min=4, max=20)], render_kw={'placeholder': '输入用户名'})
    # email = StringField('Email Address', [validators.Length(min=6, max=35)])
    # 密码和确认密码,需要验证是否一致,注意字段名不能填错
    password = PasswordField('密码:', [
        validators.DataRequired(),
        validators.EqualTo('confirm', message='密码必须一致')
    ])
    confirm = PasswordField('确认密码:')
    # 这个是是否接收条件
    # accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])
    # 提交按钮
    submit = SubmitField('注册')


@app.route('/register', methods=['GET', 'POST'])
def register():
    reg_form = RegisterForm()

    if request.method == 'POST':
        if reg_form.validate_on_submit():
            # 注册进数据库
            print(reg_form.validate_on_submit())
            # user = User(form.username.data, form.email.data,
            #             form.password.data)
            # db_session.add(user)
            # flash('Thanks for registering')
            return 'register success'
            # return redirect(url_for('login'))
        else:
            print('err', reg_form.validate_on_submit())
            return '验证不成'
    return render_template('register.html', form=reg_form)

if __name__ == '__main__':
    manager.run()

迁移过程

xx.py指代你使用的文件名

python xx,py db init
python xx.py db migrate-m'解释版本'
python xx.py db upgrade

最后查看数据库,存在你建的模型就成功了

返回以前的版本

可以根据history命令找到版本号,然后传给downgrade命令:

python xx.py db history

输出格式: -> 版本号 (head), initial migration
回滚到指定版本

python xx.py db downgrade 版本号

你可能感兴趣的:(Flask)