flask快速入门笔记七_第三方模块

  1 Flask-WTF

  2 Flask-SQLAlchemy( 主要涉及password验证 )

  3 Flask-Login

    3.1 登录用户 login_user

    3.2 模板中的 current_user

    3.3 保护路由 @login_required

    3.4 登出用户 logout_user

  4 Flask-Script 命令行控制

  5 Flask-Migrate 命令行控制db

  6 Flask-Markdown

 

1 Flask-WTF 

步骤一 : 创建表单

import os, sys
from flask_wtf import Form
from wtforms import StringField, PasswordField, BooleanField, SubmitField  #这是wtform的支持的html标准字段
from wtforms.validators import DataRequired, Length, Regexp, EqualTo    #wtform内建的验证函数
from wtforms import ValidationError  #报错时使用
out = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(out)
import model
User = model.User


class LoginForm(Form):
    username = StringField('Username', validators=[DataRequired(), Length(1, 64)])
    password = PasswordField('Password', validators=[DataRequired()])
    #  remeber_me = BooleanField('Keep me Logged in')
    submit = SubmitField('Log In')


class RegistrationForm(Form):
    username = StringField('Username', validators=[
        DataRequired(), Length(1, 64), Regexp(
            regex='^[A-Za-z][A-Za-z0-9_]*$', message='username must have only letters, numbers,etc')])
    password = PasswordField('Password', validators=[
        DataRequired(), EqualTo('password2', message='Password must match')])
    password2 = PasswordField('Confirm password', validators=[DataRequired()])
    submit = SubmitField('Register')

    #  以validate_开头的函数且后面跟着字段名(比如username),这个方法会和常规验证函数一起调用
    def validate_username(self, field):
        if User.query.filter_by(username=field.data).first():
            raise ValidationError('Username already in use.')

其中 validate_username() 函数是验证表单

以validate_开头的函数且后面跟着字段名(比如username),这个方法会和常规验证函数一起调用

步骤二:把表单渲染成html

方式一,直接写html

<form method="POST" action="/">
    {{ form.hidden_tag() }}
    {{ form.name.label }} {{ form.name(size=20) }}
    <input type="submit" value="Go">
</form>

其中form.hidden_tag()方法是一个隐藏的 DIV 标签中渲染任何隐藏的字段,包括 CSRF 字段

方式二, 利用flask_bootstrap的wtf.quick_form()方法

{% import "bootstrap/wtf.html" as wtf %}
....
{{ wtf.quick_form(form) }}

步骤三:在视图函数中处理表单

遵循POST/redirect/GET模式

@auth.route('/login', methods=['GET', 'POST'])
def v_login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user is not None and user.verify_password(form.password.data):
            login_user(user)  # 相当于记住session
            return redirect(url_for('main.v_index'))
        flash('Invalid username or password.')
    return render_template('auth/login.html', form=form)

 

2 Flask-SQLAlchemy(主要涉及password验证)

from werkzeug.security import generate_password_hash, check_password_hash  # 将密码加密和检查加密后的密码
from app2 import db
from datetime import datetime


class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))
    created = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    comments = db.relationship('Comment', backref='users')
    # 该函数是password只有只写属性,如果被读则直接报错
    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')
    # 该函数用于当password被创建时,会被自动set成加密后的password
    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)
    # 该函数用检测password与password_hash的值是否相同
    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

为了安全,user的密码会用Werkzeug提供的密码散列

generate_password_hash 是生成散列

check_password_hash 是检查散列

@password.setter(def password()) 方法会将输入的password自动setter成password_hash

最后的 verify_password 方法用于验证password_hash是否相同

 

3 Flask-Login 

步骤一:配置应用

from flask_login import LoginManager
login_manager = LoginManager()  # 创建对象
login_manager.init_app(app)  # 配置
login_manager.session_protection = 'strong'  #设置session加密强度
login_manager.login_view = 'auth.v_login'  # 设置默认的登录函数

步骤二:user_loader 回调

@login_manager.user_loader
def load_user(user_id):
    return User.query.fiter_by(user_id).first()

步骤三:继承UserMixin

User的model一定要实现 is_authenticated; is_active; is_anonymous; get_id 四个方法

而User的model可以通过继承 UserMixin 来实现

from flask_login import UserMixin

class User(db.Model, UserMixin):
    pass

 

3.1 登录用户 login_user  

login_user(user, form.remember_me.data)  #记住session

这个方法可以让用户登录

@app.route('/login', methods=['GET', 'POST'])
def login():
    # Here we use a class of some kind to represent and validate our
    # client-side form data. For example, WTForms is a library that will
    # handle this for us, and we use a custom LoginForm to validate.
    form = LoginForm()
    if form.validate_on_submit():
        # Login and validate the user.
        # user should be an instance of your `User` class
        login_user(user, form.remember_me.data)  #记住session

        flask.flash('Logged in successfully.')

        next = flask.request.args.get('next')
        # next_is_valid should check if the user has valid
        # permission to access the `next` url
        if not next_is_valid(next):
            return flask.abort(400)

        return flask.redirect(next or flask.url_for('index'))
    return flask.render_template('login.html', form=form)

警告: 必须验证 next 参数的值。如果不验证的话,你的应用将会受到重定向的攻击。

 

3.2 模板中的 current_user  

每个模板都可以用 current_user 来代理访问登录的用户。

{% if current_user.is_authenticated %}
  Hi {{ current_user.name }}!
{% endif %}

 

3.3 保护路由 @login_required  

通过@login_required 来实现

 

3.4 登出用户 logout_user 

@app.route("/logout")
@login_required
def logout():
    logout_user()
    return redirect(somewhere)

 

4 Flask-Script 命令行控制  

 命令行控制

# 调用runserver命令行 python manager.py runserver
# 调用db的命令行 python manager.py db db_init

manager.py

from flask_script import Manager

from myapp.mainapp import app
from db_manger import db_manager

manager = Manager(app)

manager.add_command('db', db_manager)  # 将db_manager添加到命令行

@manager.command
def runserver():
    print 'server run'

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

db_manager.py 中间db命令行 和 flask_migrate 思路一样

from flask_script import Manager

db_manager = Manager()

@db_manager.command
def db_init():
    print 'db init'

@db_manager.command
def db_drop():
    print 'db drop'

 

5 Flask-Migrate 命令行控制db 

1) 每次ORM更新时候,后期修改字段不会映射到数据库中,必要要 drop 再 create 这样很繁琐。

flask-migrate解决了这一问题

2) 使用 flask-migrate 需要借助 flask-script 然后使用命令行

3) flask_migrate 相关命令

  python manager.py db init :初始化一个歉意脚本环境,只需执行一次

  python manager.py db migrate : 将模型生成迁移文件,更改model就要执行这个文件

  python manager.py db upgrade : 将迁移文件真正映射到数据库中,每次运行 migrate 后都要执行这行命令。

4) 注意 :和 create_all 同理,如果要将模型映射到数据库,必要将mode 导入到目标文件也就是 manager.py 中。

# coding=utf-8

from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand

from myapp.mainapp import app
from myapp.db_middle import db
from db_manger import db_manager

manager = Manager(app)

# 1 先将app和db绑定
migrate = Migrate(app, db)

# 把 MigrateCommand 命令添加到 manager 中
# db_manager 和 MigrateCommand 道理一样
manager.add_command('db', MigrateCommand)

 

6 Flask-Markdown  

步骤一: 配置应用

from flaskext.markdown import Markdown
Markdown(app)

步骤二 编辑html:

<body>
{% filter markdown %}
#My Markdown
***
* ##Some intersting things
I just want to test hahaaaaaaa
{% endfilter %}
</body>

 

posted @ 2017-01-18 17:52  fuzzier  阅读(384)  评论(0编辑  收藏  举报