Flask DAY 2

 

一、请求(request)与响应(response)原理

当我们在浏览器中的地址栏中输入这个URL,然后按下Enter,稍等片刻,浏览器会显示一个问候页面。这背后到底发生了什么?你一定可以猜想到,这背后也有一个类似我们编写的程序运行着。它负责接收用户的请求,并把对应的内容返回给客户端,显示在用户的浏览器上。事实上,每一个Web应用都包含这种处理模式,即“请求-响应循环(Request-Response Cycle)”:客户端发出请求,服务器处理请求并返回响应,如下图所示:

 

 

 

 附注 客户端(Client Side)是指用来提供给用户的与服务器通信的各种软件。在本书中,客户端通常指Web浏览器(后面简称浏览器),比如Chrome、Firefox、IE等;服务器端(Server Side)则指为用户提供服务的服务器,也是我们的程序运行的地方。

 

这是每一个Web程序的基本工作模式,如果再进一步,这个模式又包含着更多的工作单元,

 

下图展示了一个Flask程序工作的实际流程:

 

 

 

从上图可以看出,HTTP在整个流程中起到了至关重要的作用,它是客户端和服务器端之间沟通的桥梁。

当用户访问一个URL,浏览器便生成对应的HTTP请求,经由互联网发送到对应的Web服务器。Web服务器接收请求,通过WSGI将HTTP格式的请求数据转换成我们的Flask程序能够使用的Python数据。在程序中,Flask根据请求的URL执行对应的视图函数,获取返回值生成响应。响应依次经过WSGI转换生成HTTP响应,再经由Web服务器传递,最终被发出请求的客户端接收。浏览器渲染响应中包含的HTML和CSS代码,并执行JavaScript代码,最终把解析后的页面呈现在用户浏览器的窗口中。

Request对象(from flask import Flask,request)

这个请求对象封装了从客户端发来的请求报文,我们能从它获取请求报文中的所有数据。

我们先从URL说起。假设请求的URL是http://helloflask.com/hello?name=Grey,当Flask接收到请求后,请求对象会提供多个属性来获取URL的各个部分,常用的属性如下表所示:

 

 

除了URL,请求报文中的其他信息都可以通过request对象提供的属性和方法获取,其中常用的部分如下表所示:

 

 

 

在我们的示例程序中实现了同样的功能。当你访问http://localhost:5000/hello?name=Grey,页面加载后会显示“Hello, Grey!”。这说明处理这个URL的视图函数从查询字符串中获取了查询参数name的值,如下所示:

 

 

from flask import Flask, request

app = Flask(__name__)

@app.route('/hello')
def hello():
  print(request.method) #打印请求方式
  print(request.url) #打印请求地址
name = request.args.get('name', 'Flask') # 获取查询参数name的值 return '<h1>Hello, %s!</h1>' % name # 插入到返回值中

需要注意的是,和普通的字典类型不同,当我们从request对象中类型为MutliDict或ImmutableMultiDict的属性(比如files、form、args)中直接使用键作为索引获取数据时(比如request.args['name']),如果没有对应的键,那么会返回HTTP 400错误响应(Bad Request,表示请求无效),而不是抛出KeyError异常,如下图所示。为了避免这个错误,我们应该使用get()方法获取数据,如果没有对应的值则返回None;get()方法的第二个参数可以设置默认值,比如requset.args.get('name', 'Human')。

 

 

二、从路径中获取参数

Flask不同于Django直接在定义路由时编写正则表达式的方式,而是采用转换器;

URL中路径参数的获取:

语法:<>

作用:提取URL路径参数

效果:将该位置数据以字符串格式匹配,值同样为字符串类型,转换器中的值为参数名传入视图

@app.route('/index/<id>',methods=["GET","POST"])    
#def first_flask(id):    #视图函数
        print(id)
     return"hello user %S!" % id      


  

 三、设定视图函数能够处理的请求方式

HTTP有很多URL方法的。默认路由只回应GET请求,但是我们可以在装饰器app.route中传递methods参数改变请求方式,

当我们需要视图函数能够处理多种请求时,需要在对应的视图函数的装饰器上进行修改增加一行代码:methods=["get","post"]如果还有其他的请求方式需要添加,在括号中继续加入对应的请求方式即可。

@app.route('/index/<id>',methods=["GET","POST"])
    

四、返回指定的前端网页(利用render_template()渲染html)

render_template()有什么用?
  在Python代码中 直接生成 HTML 缺点很多,比如笨拙,效率低,可读性差。因此, Flask 提供了 Jinja2 模板引擎来帮助开发者高效灵活生成HTML。
使用该方法可以渲染模板,你只要提供模板名称和需要作为参数传递给模板的变量就行了.
html模板文件的位置
模板即自己写好的模板html文件,需要放在templates文件夹内。目录结构如下:

 

/application.py
/templates #创建一个新的空文件夹且命名templates.
    /hello.html

 

实例 

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
   
    return render_template('files_list.html')

if __name__="__main__" :
app.run(debug=True)
 

 

五、返回JSON数据(import json,from flaskimport Flask,jsonify)

在前后端分离的时代,后端一般返回前端的数据就是json格式的响应数据。
而json格式的响应数据其实实际上就是一个字符串。

要知道Flask如何返回json响应数据,首先就需要知道如何将字典dict转化为json字符串。

In [1]: import json
In [2]: data = {"user_name":"libai", "user_pwd": "123456"} 
In [3]: type(data)
Out[3]: dict
# 将dict转为json字符串
In [4]: res = json.dumps(data) 
In [5]: res
Out[5]: '{"user_name": "libai", "user_pwd": "123456"}' 
In [6]: type(res)
Out[6]: str 
# 将json字符串转为dict
In [7]: rec = json.loads(res)
In [9]: rec
Out[9]: {'user_name': 'libai', 'user_pwd': '123456'} 
In [10]: type(rec)
Out[10]: dict

视图函数使用json库返回json响应数据

from flask import Flask, request
import json 
# 实例化app
app = Flask(import_name=__name__)
@app.route('/login', methods=["GET","POST"])
def login():
    data = {
        "user_name": "libai",
        "user_age": 18,
    } 
    res_json = json.dumps(data)

    return res_json
 
if __name__ == '__main__':
    app.run(debug=True)

 

在浏览器请求如下:

 

 

如果单纯直接返回响应消息,Content-Type:text/html 是不正确的,应该改为application/json 才对。

修改响应消息的headers如下:

from flask import Flask, request, abort, make_response
 
import json
 
# 实例化app
app = Flask(import_name=__name__)
 
@app.route('/login', methods=["GET","POST"])
def login():
 
    data = {
        "user_name": "libai",
        "user_age": 18,
    }
 
    res_json = json.dumps(data)
 
    # return 响应体, 状态码, 响应头
    return res_json, 200, {"Content-Type":"application/json"}
 
if __name__ == '__main__':
    app.run(debug=True)

在浏览器的请求响应如下:

 

 

 

可以看到正常返回json数据了。

但是可以感觉到这样其实挺麻烦的。在Flask框架中有一个jsonify的方法可以将这个过程简化。

使用jsonify来返回json响应数据

from flask import Flask, jsonify
 
# 实例化app
app = Flask(import_name=__name__)
 
@app.route('/login', methods=["GET","POST"])
def login():
 
    data = {
        "user_name": "libai",
        "user_age": 18,
    }
 
    return jsonify(data)
 
if __name__ == '__main__':
    app.run(debug=True)

浏览器请求如下:

 

 

可以看到,使用jsonify返回json响应数据是最简单的一种方式。 

 

  • 另外jsonify不单单可以将dict转为json响应数据,还可以直接往里面写参数值

 

 

jsonify(token=123456, gender=0)

 

 示例如下: 

 

from flask import Flask, jsonify
 
# 实例化app
app = Flask(import_name=__name__)
 
@app.route('/login', methods=["GET","POST"])
def login():
 
    return jsonify(token=123456, gender=0)
 
if __name__ == '__main__':
    app.run(debug=True)

 

浏览器请求如下:  

 

 

 

  

  

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐