zoukankan      html  css  js  c++  java
  • Flask的Blueprints和Views

    Flask的view函数是用来对请求作出响应的。单个URL能匹配到单个View,那么多个类似的URL,比如:

    /auth/register
    /auth/login
    /auth/logout
    

    有没有什么比较优雅的写法呢?

    Blueprints

    Blueprints就是一个路由分组,可以把共同的路由前缀注册为一个Blueprint,比如:

    flaskr/auth.py文件中先定义一个Blueprint:

    import functools
    
    from flask import (
        Blueprint, flash, g, redirect, render_template, request, session, url_for
    )
    from werkzeug.security import check_password_hash, generate_password_hash
    
    from flaskr.db import get_db
    
    bp = Blueprint('auth', __name__, url_prefix='/auth')
    
    • 'auth'是Blueprint的名字。
    • __name__用来告诉Blueprint它的定义位置。
    • url_prefix就是路由前缀。

    接着在flaskr/__init__.py文件中注册:

    def create_app():
        app = ...
        # existing code omitted
    
        from . import auth
        app.register_blueprint(auth.bp)
    
        return app
    

    Views

    定义和注册了Blueprints后就可以在view中使用了。比如:

    ①在flaskr/auth.py文件中添加一个注册view:

    @bp.route('/register', methods=('GET', 'POST'))
    def register():
        if request.method == 'POST':
            username = request.form['username']
            password = request.form['password']
            db = get_db()
            error = None
    
            if not username:
                error = 'Username is required.'
            elif not password:
                error = 'Password is required.'
    
            if error is None:
                try:
                    db.execute(
                        "INSERT INTO user (username, password) VALUES (?, ?)",
                        (username, generate_password_hash(password)),
                    )
                    db.commit()
                except db.IntegrityError:
                    error = f"User {username} is already registered."
                else:
                    return redirect(url_for("auth.login"))
    
            flash(error)
    
        return render_template('auth/register.html')
    
    • @bp.route就会把路由前缀加到'/register'上拼成/auth/register
    • request.form是一个字典,可以读取接口入参。
    • db.execute执行SQL语句。db.commit()提交。
    • redirect在注册成功后重定向到登录页面。
    • url_for根据view名字来获取url,因为这里用到了Blueprint,所以入参是"auth.login"。如果没有用Blueprint,url_for()函数入参就写view函数名即可。

    ②在flaskr/auth.py文件中添加一个登录view:

    @bp.route('/login', methods=('GET', 'POST'))
    def login():
        if request.method == 'POST':
            username = request.form['username']
            password = request.form['password']
            db = get_db()
            error = None
            user = db.execute(
                'SELECT * FROM user WHERE username = ?', (username,)
            ).fetchone()
    
            if user is None:
                error = 'Incorrect username.'
            elif not check_password_hash(user['password'], password):
                error = 'Incorrect password.'
    
            if error is None:
                session.clear()
                session['user_id'] = user['id']
                return redirect(url_for('index'))
    
            flash(error)
    
        return render_template('auth/login.html')
    
    • fetchone()取一行数据,fetchall()取多行数据。

    • 登录成功后会把user_id存入session中,session是一个字典,这样后续请求就可以用到这个数据。比如:

      @bp.before_app_request
      def load_logged_in_user():
          user_id = session.get('user_id')
      
          if user_id is None:
              g.user = None
          else:
              g.user = get_db().execute(
                  'SELECT * FROM user WHERE id = ?', (user_id,)
              ).fetchone()
      

      值得注意的是@bp.before_app_request有点像setup,就是在所有请求前先运行这一段代码。

    ③在flaskr/auth.py文件中添加一个登出view:

    flaskr/auth.py
    @bp.route('/logout')
    def logout():
        session.clear()
        return redirect(url_for('index'))
    
    • session.clear()清除session。

    ④最后可以在在flaskr/auth.py文件中顺手写一个装饰器,用来做认证鉴权:

    def login_required(view):
        @functools.wraps(view)
        def wrapped_view(**kwargs):
            if g.user is None:
                return redirect(url_for('auth.login'))
    
            return view(**kwargs)
    
        return wrapped_view
    
    

    在需要登录才能访问的view上,就可以加上这个login_required装饰器。

    参考资料:

    https://flask.palletsprojects.com/en/2.0.x/tutorial/views/

  • 相关阅读:
    博客基础_django入门_python从入门到实践_用户登陆、注销与注册
    博客基础_django_python从入门到实践_添加主题_添加条目_编辑条目
    python学习(六)
    python作业(五)
    python学习(五)
    python学习(四)
    python作业(三)
    python学习(三)
    python作业(二)
    python学习(二)
  • 原文地址:https://www.cnblogs.com/df888/p/15609323.html
Copyright © 2011-2022 走看看