Flask自带的常用组件介绍

作者: 何柯君 | 来源:发表于2017-09-25 10:15 被阅读226次

    [TOC]
    Flask的优点是灵活小巧,三行代码即可运行一个web服务器,但基于Flask构建的功能并不比Django弱,关键就就是除了flask自带的基础功能外,还有丰富的组件进行支持,本文先对常用的自带组件进行简单的介绍。测试的Flask版本是0.12。

    在构建Flask应用导入的时候,通常是from flask import Flask的方式开始的,说明flask这个python package里面应该还藏了不少好东西,从源码来看看:

    from werkzeug.exceptions import abort
    from werkzeug.utils import redirect
    from jinja2 import Markup, escape
    
    from .app import Flask, Request, Response
    from .config import Config
    from .helpers import url_for, flash, send_file, send_from_directory, \
        get_flashed_messages, get_template_attribute, make_response, safe_join, \
        stream_with_context
    from .globals import current_app, g, request, session, _request_ctx_stack, \
        _app_ctx_stack
    from .ctx import has_request_context, has_app_context, \
        after_this_request, copy_current_request_context
    from .blueprints import Blueprint
    from .templating import render_template, render_template_string
    
    # the signals
    from .signals import signals_available, template_rendered, request_started, \
        request_finished, got_request_exception, request_tearing_down, \
        appcontext_tearing_down, appcontext_pushed, \
        appcontext_popped, message_flashed, before_render_template
    
    # We're not exposing the actual json module but a convenient wrapper around
    # it.
    from . import json
    
    # This was the only thing that Flask used to export at one point and it had
    # a more generic name.
    jsonify = json.jsonify
    
    # backwards compat, goes away in 1.0
    from .sessions import SecureCookieSession as Session
    json_available = True
    

    Flask自带组件基本上都在这里了,我们一一来分析这些组件的功能及基本的用法。

    Flask

    Flask应用的主类,在源码分析中提到,不再赘述。这里给一个Flask应用的经典样例,请务必注意下面的代码都是在此样例基础上进行拓展的

    #示例-1
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    if __name__ == '__main__':
        app.run()
    

    render_template:

    def render_template(template_name_or_list, **context)

    template_name_or_list参数是模板名称,context参数接受模板中已经定义的变量值。
    Jinja是Flask的模板引擎,提供对HTML页面的数据渲染,render_template是Flask中调用template目录的html模板并渲染数据。代码示例:

    #示例-2
    from flask import render_template
    
    @app.route("/")
    def index():
        name="He Kejun"
        return render_template("index.html",name=name)
    

    上述的代码中调用了/template/index.html模板,并将“name: He Kejun”这一数据渲染进该模板其可以直接通过Hello, {{name}}的方式显示‘Hello, He Kejun'


    session

    flask的session机制,Flask从服务器通过浏览器的cookie保存信息,该信息通过应用的秘钥进行加密确保数据安全。session在用户身份认证和数据共享提供较好的帮助。样例:

    #示例-3
    from flask import session
    app.config["SECRET_KEY"]="YOU CAN NOT GUESS ME" #加密的秘钥,建议放在配置文件中
    
    @app.route("/")
    def index():
        session["name"]="kejun"
        return "hello,world"
    
    @app.route("/name")
    def name():
        return session["name"]
    
    

    首先访问http://127.0.0.1:5000 生成用户名,查看浏览器的cookie可以看到session已经写入了,这时候再访问http://127.0.0.1:5000/name就可以看到名字了,在两个HTTP请求之间共享了{name: kejun}这个数据。

    url_for

    def url_for(endpoint, **values):

    根据已经定义好的view函数来创建URL到指定的endpoint,Flask的endpoint可以理解为Restful框架中资源。输入的endpoint是函数名,values是关键字参数,每个关键字参数对应URL规则的变量部分,未知变量部分被插入到URL中作查询参数,具体的样例,我使用了官网的样例

    #示例-4
    from flask import url_for
    
    @app.route("/")
    def index(): pass
    
    @app.route("/login")
    def login(): pass
    
    
    @app.route("/user/<username>")
    def profile(username):pass
    
    with app.test_request_context():
        print(url_for("index))  #/
        print(url_for("login"))  #/login
        print(url_for("login",next="/"))  #/login?next=/
        print(url_for("profile,username="kejun"))  @/user/kejun
    

    redirect

    def redirect(location, code=302, Response=None):

    参数location是跳转的目标位置,code是HTTP响应码默认是302(临时移动),也可以设置为301(永久移动,即所请求的文档在别处),303(参见其他信息),305(使用代理),不可以是300(多重选择),304(未修正更新)。
    redirect的作用是重定向,设置响应并跳转到指定的位置。在Flask中通常与url_for这个功能一起使用。应用实例:

    #示例-5
    from flask import redirect
    
    @app.route("/")
    @app.route("/index")
    def index():
       return redirect(url_for("blog"))
    
    @app.route("/blog")
    def blog():  pass
    
    

    在示例-5中,我们可以将一些用户可能会访问的链接重定向到博客主页上。

    flash

    def flash(message, category='message'):

    参数message是消息内容,category是消息类型,方便前端过滤。
    Web设计中提供用户的友好性是及时将反馈提供给用户。消息闪现Flash提供了一个非常简单的机制。

    #示例-6-1
    from flask import flash
    
    def print_message():
        flash("This is a message","message")
        return "Message Page"
    
    def print_error()
        flash("This is a error","error")
        return "Error Page"  
    

    在前端,我们可以这样定义HTML页面从而显示内容

    #示例-6-2
    {% with msgs = get_flashed_messages(category_filter=["message"]) %}
        {% if msgs %}
            {% for msg in msgs %}
                <p>{{msg}}</p>
            {% endfor %}
        {% endif %}
    {% endwith %}
    {% with errors= get_flashed_messages(category_filter=["error"]) %}
        {% iferrors%}
             {% for errorinerrors%}
                   <p>{{error}}</p>
             {% endfor %}
        {% endif %}
    {% endwith %}
    
    

    make_response

    def make_response(*args):

    Flask会自动将view函数返回的转换成响应对象,除此之外,你可以通过调用make_response

    #示例-7
    from flask import make_response
    
    def index():
          return render_template('index.html', foo=42)
    
    def index():
           response = make_response(render_template('index.html', foo=42))
           resp.set_cookie("am_i_handsome","yes") #设置cookie
           return response
    

    在上述的示例中,通过make_response,还可以定制cookie。也就是说,通过make_response你可以个性化定制返回的响应对象。

    jsonify

    对于数据进行json转化,应用于通过ajax方式访问时需要返回json数据。

    #示例-8
    from flask importjsonify
    
    @app.route("/update_user_name",methods=['GET', 'POST'])
    def update_user_name():
        ip=request.headers.get('X-Real-Ip', request.remote_addr)
        user_name=request.args.get('new_user_name',"",type=str)
        if user_name:
            if set_user_name(ip,user_name):
                return jsonify(return_code="1")
        return jsonify(return_code="0")
    
    

    blueprint

    blueprint蓝图是flask自带的一种拓展已有应用结构的方式,这是Flask在中大型Web应用中的一种框架设计。蓝图把把功能类似或者同一模块下的视图函数组合在一起,基于蓝图,我们可以把Flask应用拆分成不同的组件。每个蓝图都可以自定义自己的模板文件目录和静态目录。定义好的蓝图目录可以通过注册的方式加入Flask应用中。代码示例如下:

    #示例-9-1
    from flask import Blueprint
    
    example=Blueprint('example',__name__,template_folder='templates/example',static_folder='static/example',url_prefix='/example')
    
    #蓝图example下的视图函数
    @example.route
    def index():
        return render_template("index.html")
    

    一个蓝图就是一个模块,上述的example蓝图创建好后,需要注册到Flask应用中,样例代码如下:

    示例-9-2
    from flask import Flask
    from yourapplication.examples import example
    
    app = Flask(__name__)
    app.register_blueprint(example)
    

    本文之前介绍了url_for的使用方法,在蓝图中使用url_for定位视图函数需要增加蓝图名称,如定位到上述index视图函数url_for('example.index')

    request

    Flask构建了一个与请求相关的全局变量,在所有的视图函数及模板中都可以访问该对象。应用示例如下:

    #示例-10
    from flask import request
    def get_user_ip():
        ip=request.headers.get('X-Real-Ip', request.remote_addr)
        return "Request ip address is {0}".format(ip)
    

    abort

    abort是Flask中Abort类的一个实例,通常采用abort(error_code)的方式进行调用。abort的状态码最好是自己实现的错误定义,如示例-11所示。

    g

    Flask中的全局变量g,可以为特定请求临时存储任何需要的数据并且是线程安全的,当请求结束时,这个对象会被销毁,下一个新的请求到来时又会产升一个新的g。

    #示例-11
    from flask import g,session,abort,render_template
    @app.before_request
    def before_request():
        if 'user_name' in session:
            g.user=User.query.get(session['user_name'])
    
    @app.route('/admin')
    def admin():
        if g.user is None:
            abort(404)
        return render_template('admin.html')
    
    @app.errorhandler(404):
    def page_not_found():
        return render_template("404.html"),404
    
    

    send_from_directory

    def send_from_directory(directory, filename, **options):

    参数directory是文件所在目录,filename是文件名称,options参数是send_file的传入参数,options可选的参数包括 mimetype、as_attachment、attachment_filename、add_etags、cache_timeout、conditional。
    send_from_directory可以认为send_file上加了一层壳子,判断了文件路径及文件名,然后交由send_file处理,实际上将文件内容发给浏览器,所以它一个重要的应用场景是支持文件下载。
    对于文件下载,媒体数据流传输的可以再研究一下send_filestream_with_context这两个功能,也非常好用。
    示例代码为:

    #示例-11
    from flask import send_from_directory
    
    @app.route('/getfile', methods=['GET'])
    def download_file():
        return send_from_directory(r"D:\Workspace\flask_source", "aa.txt", as_attachment=True)
    

    Markup

    class Markup(text_type):

    将输入文本text_type标记为安全,不需要进行转移。
    如果将HTML作为变量通过Jinjia模板的方式作为变量插入页面中,Flask会自动尝试对HTML进行转义。这是必要的安全措施,确保恶意用户通过提交一段恶意代码并显示在页面中,从而让其他用户的浏览器进行执行。Flask同时提供两种方法来对安全的HTML不转义直接显示:一个是利用Markup类,二是利用Jinjia关键字safe。示例代码为:

    示例-12
    from flask import Markup
    @app.route("/")
    def index():
        return Markup('Hello %s!') % '<strong>kejun</strong>'#显示strong标签
    
    @app.route("/1")
    def index1():
        return 'Hello %s!' % '<strong>kejun</strong>'#将strong标签转移成显示
    

    current_app

    应用上下文对象,官方文档有详细的介绍,

    相关文章

      网友评论

        本文标题:Flask自带的常用组件介绍

        本文链接:https://www.haomeiwen.com/subject/fcurextx.html