[Flask] Flask的请求与响应

news/2024/10/19 2:18:13/

1.Flask的请求

如果以GET请求访问URL,例如URL是127.0.0.1:5000/?name=andy&age=18,那么如何获取这个URL的参数?如果以POST请求提交一个表单,那么又如何获取表单中各个字段值呢?

Flask提供的Request请求对象就可以实现上述功能

Request请求对象的常用属性和方法

属性或方法说明
args存储url请求中的查询参数,返回类似于字典的数据
method存储请求中使用的HTTP方法,例如GET或POST
form存储请求提交的所有表单数据,返回类似于字典的数据
files存储请求上传的所有文件,返回类似于字典的数据
url存储客户端请求的完整URL
host存储请求的域名
headers存储HTTP请求的请求头信息,返回类似于字典的数据
cookies存储请求的所有cookie,返回类似于字典的数据

1.1 GET请求

使用request.args.get()方法就可以获取GET请求参数

实例1:获取GET请求参数

获取127.0.0.1:5000/?name=andy&age=18这个URL中的name和age两个参数,在资源文件目录下创建一个run.py文件

目录结构

代码如下所示

# run.py
from flask import Flask, request
app = Flask(__name__)@app.route('/')
def index():name = request.args.get('name')age = request.args.get('age')message = f'姓名:{name}\n年龄:{age}'return messageif __name__ == '__main__':app.run(debug=True)

运行run.py文件,在浏览器中访问网址: 127.0.0.1:5000/?name=andy&age=18,运行结果如下图所示

1.2 POST请求

使用request.args.post()方法可以接收POST请求参数,如果接收表单数据,可以使用request.from对象

实例2: 获取表单提交信息

首先创建一个run.py文件,在该文件中定义一个login路由,代码如下所示

# run.py
from flask import Flask, request, render_template
app = Flask(__name__)@app.route('/login', methods=['GET', 'POST'])
def login():if request.method == 'POST':username = request.form['username']password = request.form['password']message = f'用户名是:{username}</br>密码是:{password}'return messagereturn render_template('login.html')if __name__ == '__main__':app.run(debug=True)

然后在run.py同级目录下创建"templates"文件夹,在"templates"路径下创建login.html模板文件

目录结构

代码如下所示

<!--login.html-->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>用户登录</title>
</head>
<body><form action="" method="post"><div><label for="username">用户名</label><input type="text" id="username" name="username" value=""></div><div><label for="password">密&nbsp;&nbsp;&nbsp;&nbsp;码</label><input type="password" id="password" name="password" value=""></div><button type="submit">提交</button></form>
</body>
</html>

运行run.py文件,在浏览器中访问网址127.0.0.1:5000/login,显示表单页面,用户名输入andy,密码输入123456

单击【提交】按钮,运行结果如下所示

文件上传 

在使用Web表单时,经常会使用到上传文件功能,request.files对象可以获取与表单相关的数据

案例3: 实现上传用户图片功能

目录结构

首先定义一个路由函数upload()用于上传图片,然后提交上传的图片,在另一个路由函数uploaded_file()中显示图片内容,具体操作步骤如下

① 在"templates"目录下创建文件上传模板upload.html,代码如下所示

<!--upload.html-->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>上传图片</title>
</head>
<body><!--form表单中设置enctype="multipart/form-data",用于上传文件--><form action="" method="post" enctype="multipart/form-data"><div><label for="avatar">上传图片</label><input type="file" id="avatar" name="avatar" value=""></div><button type="submit">提交</button></form>
</body>
</html>

② 创建一个run.py文件,在该文件中编写upload()路由函数,当接受GET请求时,显示模板文件内容;当接受POST请求时,上传图片

代码如下所示

@app.route('/upload',methods=['GET','POST'])
def upload():"""头像上传表单页面:return:"""if request.method == 'POST':# 接受头像字段avatar = request.files['avatar']# 判断文件是否上传,已经上传文件类型是否正确if avatar and allowed_file(avatar.filename):# 生成一个随机文件名filename = random_file(avatar.filename)# 保存文件avatar.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))return redirect(url_for('uploaded_file',filename=filename))return render_template('upload.html')

上述代码中,使用request.files['avatar']接收表单中name='avatar'的字段值,然后检测用户是否上传了图片,并且使用allowed_file()函数检测上传的文件类型是否满足设定的要求

allowed_file()函数代码如下所示

ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])def allowed_file(filename):"""判断上传文件类型是否允许:param filename: 文件名:return: 布尔值True或False"""return '.' in filename and \filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

接下来使用random_file()函数为上传的文件重新创建一个随机的不重复的文件名,通过使用uuid.uuid4()生产处一个随机的几乎不可能重复的文件名,然后拼接一个完整的路径,代码如下所示

import uuiddef random_file(filename):"""生成随机文件:param filename: 文件名:return: 随机文件名"""# 获取文件后缀ext = os.path.splitext(filename)[1]# 使用uuid生成随机字符new_filename = uuid.uuid4().hex+extreturn new_filename

准备工作完成后,最后调用avartar.save()方法将图片存储到相应的路径下

③ 在run.py文件中创建uploaded_file()路由函数,显示图片内容,代码如下所示

@app.route('/uploads/<filename>')
def uploaded_file(filename):"""显示上传头像:param filename: 文件名:return: 真实文件路径"""return send_from_directory(app.config['UPLOAD_FOLDER'],filename)

send_from_directory()函数用于显示静态资源文件

上述run.py文件完整代码如下所示

# run.py
import os
import uuid
from flask import send_from_directory
from flask import Flask, request, render_template, redirect, url_forapp = Flask(__name__)
UPLOAD_FOLDER = os.path.join(app.root_path, 'uploads')
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDERdef allowed_file(filename):"""判断上传文件类型是否允许:param filename: 文件名:return: 布尔值True或False"""return '.' in filename and \filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONSdef random_file(filename):"""生成随机文件:param filename: 文件名:return: 随机文件名"""# 获取文件后缀ext = os.path.splitext(filename)[1]# 使用uuid生成随机字符new_filename = uuid.uuid4().hex+extreturn new_filename@app.route('/upload', methods=['GET', 'POST'])
def upload():"""头像上传表单页面"""if request.method == 'POST':# 接受头像字段avatar = request.files['avatar']# 判断文件是否上传,已经上传文件类型是否正确if avatar and allowed_file(avatar.filename):# 生成一个随机文件名filename = random_file(avatar.filename)# 保存文件avatar.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))return redirect(url_for('uploaded_file', filename=filename))return render_template('upload.html')@app.route('/uploads/<filename>')
def uploaded_file(filename):"""显示上传头像:param filename: 文件名:return: 真实文件路径"""return send_from_directory(app.config['UPLOAD_FOLDER'], filename)if __name__ == '__main__':app.run(debug=True)

执行run.py程序文件,在浏览器中输入网址: http://127.0.0.1:5000/upload,显示上传图片页面,单击【浏览】按钮,弹出一个选择框,选择一个图片后,单击【打开】按钮,会将图片文件名显示在【浏览】按钮右侧

上传图片页面
选择需要上传的图片
图片文件名成功显示

单击【提交】按钮上传文件,如果上传成功,页面将跳转至uploads,在该页面显示图片内容,运行结果如下图所示

显示上传的图片内容

此时,图片被上传到设置的路径下,并创建了一个随机的文件名

上传图片所在路径和随机文件名

1.3 钩子函数的应用

有时需要对请求进行预处理(preprocessing)和后处理(postprocessing),这时可以使用Flask提供的一些请求钩子(Hook),它们可以用来注册在请求处理的不同阶段执行的处理函数

Flask的请求钩子指的是在执行视图函数前后执行的一些函数,我们可以在这些函数里面做一些操作 

Flask利用装饰器给我们提供了四种钩子函数

before_first_request: 在处理第一个请求前执行,比如链接数据库操作

before_request: 在每次请求前执行,比如权限校验

after_request: 每次请求之后调用,前提是没有未处理的异常抛出

teardown_request: 每次请求之后调用,即使有未处理的异常抛出

实例4: 使用请求钩子,在执行视图函数前后执行相应的函数

目录结构

创建一个run.py文件,在该文件中定义一个index视图函数,然后定义before_first_request、before_request、after_request和teardown_request四个钩子,代码如下所示

# run.py
from flask import Flask
app = Flask(__name__)@app.route('/')
def index():print('视图函数执行')return 'index page'# 在第一次请求之前运行
@app.before_first_request
def before_first_request():print('before_first_request')# 在每一次请求前都会执行
@app.before_request
def before_request():print('before_request')# 在请求之后运行
@app.after_request
def after_request(response):# response就是前面的请求处理完毕之后,返回的响应数据,前提是视图函数没有出现异常print('after_request')return response# 无论视图函数是否出现异常,每一次请求之后都会调用,会接收一个参数,参数是服务器出现的错误信息
@app.teardown_request
def teardown_request(error):print('teardown_request: error %s' % error)if __name__ == '__main__':app.run(debug=True)

执行run.py程序文件,第1次在浏览器中访问网址127.0.0.1:5000时,控制台输出结果如下

before_first_request 
before_request 
视图函数执行
after_request
teardown_request: error None

2次在浏览器中访问网址127.0.0.1:5000时,控制台输出结果如下

before_request 
视图函数执行 
after_request
teardown_request: error None 

请求钩子的一些常见应用场景

1.运行程序前需要进行一些程序的初始化操作,比如创建数据库表,添加管理员用户等,这些工作可以放到使用before_first_request装饰器注册的函数中 

2.网站上要记录用户最后在线的时间,可以通过用户最后发送的请求时间来实现。为了避免在每个视图函数都添加更新在线时间的代码,可以仅在使用before_request钩子注册的函数中调用这段代码

3.在视图函数中进行数据库操作时,比如更新、插入等操作,之后需要将更改提交到数据库中,提交更改的代码就可以放到after_request钩子注册的函数中

2.Flask的响应

Response响应对象常用的属性和方法

属性或方法说明
headers响应首部
status状态
status_code状态码,文本类型
mimetypeMIME类型
set_cookie设置Cookie
get_json解析为JSON数据
is_json判断是否为JSON数据

2.1 接收响应

响应在Flask中使用Response响应对象表示,响应报文中的大部分内容由服务器处理,大多数情况下,我们只负责返回主体内容

当在浏览器中输入一个网址时,Flask会先判断是否可以找到与请求URL相匹配的路由,如果没有,则返回404响应。如果找到,则调用相应的视图函数

视图函数的返回值构成了响应报文的主体内容,当请求成功时,返回状态码默认为200

最常见的响应可以只包含主体内容,示例代码如下所示

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

响应还可以返回带状态码的形式,示例代码如下所示

@app.errorhandler(404)
def page_note_found(e):return render_template('404.html')

在大多数情况下,除了响应主体,其他部分我们通常只需要使用默认值即可

2.2 响应的格式

在HTTP响应中,数据可以通过多种格式传输

不同的响应数据格式需要设置不同的MIME类型,MIME类型在首部的Content-Type字段中定义

我们以默认的HTML类型为例,Content-Type内容如下

Content-Type: text/html; charset=utf-8

但是在特定的情况下,也会使用其他格式。我们可以通过Flask提供的make_response()方法生成响应对象,传入响应的主体作为参数,然后使用响应对象的mimetype属性设置MIME类型

常用的数据格式有纯文本、HTML、XML和JSON,它们对应的MIME类型如下

纯文本:text/plain

HTML: text/html

XML:application/xml

JSON:application/json

实例5

目录结构
# run.py
from flask import Flask, make_response
app = Flask(__name__)@app.route('/index')
def index():response = make_response('Hello World')response.mimetype = 'text/plain'return responseif __name__ == '__main__':app.run(debug=True)

运行run.py文件,在浏览器中访问网址127.0.0.1:5000/index,结果如下图所示

实例6

目录结构
# run.py
from flask import Flask, make_response, json
app = Flask(__name__)@app.route('/index')
def index():data = {'name':'Andy', 'age':18}# 调用dumps()方法将字典、列表或元组序列化(serialize)为JSON字符串response = make_response(json.dumps(data))response.mimetype = 'application/json'return responseif __name__ == '__main__':app.run(debug=True)

运行run.py文件,在浏览器中访问网址127.0.0.1:5000/index,结果如下图所示 

我们也可以使用Flask提供的jsonify()函数,只要传入数据或参数,它会对传入的参数进行序列化,转换成JSON字符串作为响应的主体,然后生成一个响应对象,并且设置正确的MIME类型

# run.py
from flask import Flask, jsonify
app = Flask(__name__)@app.route('/index')
def index():# return jsonify({'name':'Andy', 'age':18})return jsonify(name='Andy', age=18)if __name__ == '__main__':app.run(debug=True)

运行run.py文件,在浏览器中访问网址127.0.0.1:5000/index,结果如下图所示 


http://www.ppmy.cn/news/701309.html

相关文章

OCR名片识别

每年各行各业的展会陆续不断&#xff0c;而展会的作用是什么&#xff1f;相信很多参加展会的人都会收集很多的名片&#xff0c;毕竟人脉就是资源之一&#xff0c;经营好人脉&#xff0c;各方资源才会源源不断。但往往每次整理名片的时候&#xff0c;我们都会感到很烦躁&#xf…

thinkphp + 腾讯云名片识别

腾讯云&#xff1a; 搜索&#xff1a;OCR 或者 名片识别 依赖环境 PHP 5.6.33 版本及以上。获取安全凭证。安全凭证包含 SecretId 及 SecretKey 两部分。SecretId 用于标识 API 调用者的身份&#xff0c;SecretKey 用于加密签名字符串和服务器端验证签名字符串的密钥。 在…

ocr移动端名片识别

随着业务的增多&#xff0c;我们的客户资源也会越来越多。特别是在参加展会的时候&#xff0c;我们会收集到大量的名片。然而当我们还在一个一个的输入保存的时候&#xff0c;名片识别功能软件已经诞生了。 原始的方法输入保存速度慢&#xff0c;易出错&#xff0c;体验差。 …

名片识别

2019独角兽企业重金招聘Python工程师标准>>> http://www.docin.com/p-475905061.html 转载于:https://my.oschina.net/u/1049180/blog/361038

移动端名片识别SDK

随着业务的增多&#xff0c;我们的客户资源也会越来越多。特别是在参加展会的时候&#xff0c;我们会收集到大量的名片。然而当我们还在一个一个的输入保存的时候&#xff0c;名片识别功能软件已经诞生了。 原始的方法输入保存速度慢&#xff0c;易出错&#xff0c;体验差。 移…

名片识别API

一、名片识别应用背景 为了提高在移动终端上输入名片信息的速度和准确性&#xff0c;我们推出 名片识别SDK&#xff0c;以满足各个行业对名片信息自动录入的需求&#xff0c;只需在APP中集成名片识别SDK&#xff0c;用户便可通过手机拍照&#xff0c;自动录入识别名片信息。 二…

Java限流功能怎么实现?

在Java中&#xff0c;限流是一种常见的技术手段&#xff0c;用于控制系统的访问速率&#xff0c;以保护系统免受过载和滥用。以下是一些常见的Java限流实现方法&#xff1a; 1.计数器限流 这是一种简单而常见的限流方法。在该方法中&#xff0c;我们可以使用计数器来记录每个时…

名片识别信息分类python_基于PYTHON的名片识别接口调用代码实例

#!/usr/bin/python # -*- coding: utf-8 -*- import json, urllib from urllib import urlencode #---------------------------------- # 名片识别调用示例代码 &#xff0d; 聚合数据 # 在线接口文档&#xff1a; http://www.juhe.cn/docs/139 #----------------------------…