Flask 快速入门

作者: Exqlnet | 来源:发表于2018-10-25 11:57 被阅读0次

    一、Flask 简介

    Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权。

    Flask也被称为 “microframework” ,因为它使用简单的核心,并且被设计为可扩展形式。故而没有提供一些重要的功能,例如数据库和用户认证,所以开发者可以自由选择最适合程序的包,或者按照需求自行开发。

    社区成员开发了大量的不同用途的扩展,如果这还不能满足需求,你还可以使用所有Python标准包或代码库。

    image.png

    二、Flask 安装

    一般安装python后会自带pip工具,方便下载安装python各类库,如果没有自行百度。

    pip install flask
    

    三、最简单Flask应用

    # app.py
    from flask import Flask
    
    app = Flask(__name__)
    
    
    @app.route('/')
    def hello_world():
        return "Hello World!"
    
    if __name__ == '__main__':
        app.run() # 启动服务器
    

    写完后直接用python运行,默认监听本地5000端口,访问http://127.0.0.1:5000/就能看到Hello World!

    四、初始化应用

    所有Flask程序都必须创建一个程序实例,所有功能都是围绕这个实例进行的,接收自客户端的所有请求都将转交到这个对象处理。程序实例是Flask类的对象,经常使用下述代码创建一个实例:

    from flask import Flask
    app = Flask(__name__)
    

    五、路由和视图函数

    • 路由

    客户端(如Web浏览器)把请求发送给Web服务器,Web服务器再把请求发送给Flask程序实例,程序实例需要知道对每个URL请求运行哪些代码,所以保存了一个URL到Python函数的映射关系。处理URL和函数之间关系的程序称为路由

    • 视图函数

    前面最简单的Flask应用中定义了一个函数hello_world(),该函数被注册为程序根地址(/)的处理程序,也就是访问http://127.0.0.1:5000/时,会触发服务器执行hello_world()函数,函数的返回值成为响应,是客户端接收到的内容,如果客户端是Web浏览器,响应就是返回给用户的HTML文档。
    hello_world()这样的用于处理请求的函数称为视图函数。视图函数可以返回简单的HTML字符串,也可以返回一个完整的HTML文档(这里就要用到Jinja2模板引擎啦)。

    • 注册一个视图函数最常用的方法就是用app.route():
    @app.route("/")
    def hello_world():
        pass
    
    • 限制路由的请求方法
    @app.route("/", methods=["GET"])
    def hello_world():
        pass
    

    这样,要是客户端以POST的方式请求该路由,就会返回“405 Method Not Allowed”

    • 向路由函数传参
      有的时候我们需要通过url获取有用的信息,比如说知道来访者的姓名,以便在返回的欢迎语中加入他的名字。
    @app.route("/hello/<string:name>")
    def hello(name):
       return "hello, " + name
    

    上例中,在定义该路由的访问路径里加了一个<string:name>,并增加了一个同名函数参数。
    更一般的情况是<type:param>,其中type是类型,常用的有string、int,param就是参数名,它会传递到路由函数的同名参数里。

    六、启动服务器

    当Flask应用被初始化且视图函数定义好之后,就可以启动Flask应用啦。

    if __name__ == "__main__":
        app.run() # 默认监听本地5000端口
        # app.run(port=8080) 监听8080端口
    

    七、请求 - 响应循环

    说到请求,必须要先介绍一下上下文

    • 上下文(Context)

    上下文,在阅读文章时经常提到,意思是语境、语意。在程序设计中,上下文的概念也是类似的,你可以这么理解:
    通俗地讲,每一段代码都有许多外部变量,比如一个函数需要传入若干个必填的参数才能够运行,那些参数就是上下文的一部分,意味着该函数无法独立运行,需要上下文的支持。而许多函数都是需要各种参数才能运行的,这些参数组成的集合就称为上下文。

    • Flask中的上下文

    变量名 上下文 说明
    current_app 程序上下文 当前激活程序的程序实例
    g 程序上下文 上下文全局变量
    request 请求上下文 请求对象,封装了客户端发出的HTTP请求中的内容
    session 请求上下文 用户会话,用户储存同一个客户端在多个请求间需要“记住”的信息
    • 请求上下文

    请求上下文变量是在视图函数被触发时传入的一个HTTP请求对象,储存了所有客户端发送过来的数据,因此该变量只有在视图函数中才能访问。如果难以理解,你只需要记住request变量只有在视图函数中才能访问
    我们可以通过以下方式引入请求上下文变量:

    from flask import request
    
    • 请求上下文变量常用的访问操作有:

      request.args 获取所有GET请求参数
      request.form 获取所有form-data、x-www-form-urlencoded类型的请求参数
      request.json 获取所有json类型的请求参数
      request.method 获取请求方法
      request.headers 获取请求头

    • 请求钩子

      • 什么是钩子(Hook)?
        打个比方,鱼钩是用来钓鱼的,一旦鱼咬了钩,钩子就一直钩住鱼了,任凭鱼在水里怎么游,也逃不出鱼钩的控制。在程序设计里,钩子就是一个事件,钩住了某段代码,任凭这段代码这么运行,都逃不过我的钩子事件。

      • Flask里的请求钩子

        钩子 说明
        before_first_request 注册一个函数,在处理第一个请求之前运行
        before_request 注册一个函数,在每次请求之前运行
        after_request 注册一个函数,如果没有未处理的异常抛出,在每次请求之后运行
        teardown_request 注册一个函数,即使有未处理的异常抛出,也在每次请求之后运行
      • 用法

      from flask import request
      
      @app.before_request
      def app_before_request():
          print("HTTP {}  {}".format(request.method, request.url))
      

      这样在每次请求时都会输出请求方式和请求url,但其实钩子函数的作用远不止这些。

    • 响应

      通常,每个视图函数都有返回值,而最简单的就是一串字符串了,Flask默认返回的类型是text/html,状态码为200。状态码很重要,如果需要修改,我们可以这样做:

      @app.route("/")
      def hello_word():
          return "Not Found", 404
      

      当然,如果要自定义响应,最好还是引入make_response函数,该函数接受一个bytes对象(二进制数据)或者字符串作为响应主体,并返回一个响应对象response,通过这个对象我们可以自定义该响应的头部,比如修改响应头部的Content-Type和Content-Disposition来告诉客户端这个文件是需要被下载的,并且将From设置为Ncuhome来告诉客户端该文件来自家园工作室。

      @app.route("/download")
      def download():
        response = make_response(open("lesson.md", "rb").read())
        response.headers["From"] = "Ncuhome"
        response.headers["Content-Type"] = "application/octet-stream; charset=utf-8;"
        response.headers["Content-Disposition"] = "attachment;filename=lesson.md"
        return response
      
    • 快速构建一个json格式的响应

      前后端交互时,一般都是使用JSON格式数据进行交互

      from flask import jsonify
      @app.route('/hello', methods=['GET'])
      def user(user_id):
          if not user_id == 1:
              abort(404)
      
          return jsonify({
              "status": 1,
              "data": {
                  "username": "ncuhome",
                  "desc": "Hello, Ncuhomer!",
              },
              "message": "获取成功"
          })
      
    • 其他一些响应

      • 重定向
      from flask import redirect
      @app.route("/ncuos")
      def ncuos():
          return redirect("https://www.ncuos.com/")
      
      • 重定向到某个路由
      from flask import url_for
      @app.route("/redirect_to_hello")
      def redirect():
          return redirect(url_for("hello"))
      
      @app.route("/hello")
      def hello():
          return "Hello, Ncuhomer!"
      
      • 返回HTTP状态码
      from flask import abort
      @app.route("/user/<int:user_id>")
      def get_user(user_id):
          abort(404)
      

    Jinja2 模板引擎

    前面提到了Jinja2,它的作用其实是为了方便构造HTML文档、以及其他的一些文档内容(邮件等)。

    • 响应返回完整HTML
      简单举个栗子吧
      模板文件 ./template/index.html
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Ncuhome Demo</title>
      </head>
      <body>
          Hello, {{ name }}
      </body>
      </html>
      
      其中name就是我们需要填补的,它用花括号{{ }}括起来了。
      填补name并返回完整HTML:
       from flask import render_template
       @app.route("/hello/<string:name>")
       def hello(name):
           return render_template("index.html", name=name)
      
    • 模板中的for循环
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Ncuhome Demo</title>
      </head>
      <body>
        {% for user in users %}
        {{ loop.index }}: {{ user }} <br>
        {% endfor %}
      </body>
      </html>
      
       from flask import render_template
       @app.route("/users")
       def hello(name):
           users = ["Amy", "David", "Sam"]
           return render_template("index.html", users=users)
      
    • 模板中的if
      if和for类似,都拥有一个作用域,用法也一样。
      {% if name %}
         {{ name }}
      {% endif %}
      

    相关文章

      网友评论

        本文标题:Flask 快速入门

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