[Flask] Flask的请求与响应

news2024/11/26 21:29:24

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 message


if __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 message

    return 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 uuid

def random_file(filename):
    """
    生成随机文件
    :param filename: 文件名
    :return: 随机文件名
    """
    # 获取文件后缀
    ext = os.path.splitext(filename)[1]
    # 使用uuid生成随机字符
    new_filename = uuid.uuid4().hex+ext
    return 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_for

app = Flask(__name__)
UPLOAD_FOLDER = os.path.join(app.root_path, 'uploads')
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER


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


def random_file(filename):
    """
    生成随机文件
    :param filename: 文件名
    :return: 随机文件名
    """
    # 获取文件后缀
    ext = os.path.splitext(filename)[1]
    # 使用uuid生成随机字符
    new_filename = uuid.uuid4().hex+ext
    return 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 response


if __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 response


if __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.coloradmin.cn/o/701038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp开发的微信小程序之实现转发功能以及页面跳转传递、接收对象

效果图&#xff1a; 转发功能&#xff1a; <template><view class"container"><button class"share-btn" open-type"share">转发</button></view> </template><script> export default {data() {re…

规划电子类专业生涯:打造单片机/嵌入式技术专家之路

如果我是一个电子类专业的学生&#xff0c;打算将来从事单片机/嵌入式方向的职业&#xff0c;我可能会采取以下步骤来规划我的职业生涯&#xff1a; 学术准备&#xff1a;我将全面学习电子工程的基础知识&#xff0c;包括模拟电子、数字电子、信号处理等方面的知识。我会确保自…

page cache 在内核中的数据结构

page cache 在内核中的数据结构是一个叫做 address_space 的结构体&#xff1a;struct address_space。 struct address_space {struct inode *host; // 关联 page cache 对应文件的 inodestruct radix_tree_root page_tree; // 这里就是 page cache。里边缓存了文件的所有缓…

拼多多购物中的4个开关需尽快关闭,防止个人购买信息泄露

拼多多购物中的4个开关需尽快关闭&#xff0c;防止个人购买信息泄露 随着网络购物的普及&#xff0c;越来越多的人选择在拼多多等平台进行购物。然而&#xff0c;在享受便利的同时&#xff0c;我们也要警惕个人购买信息泄露的风险。在拼多多购物时&#xff0c;有些设置可能会影…

Hyperledger Fabric核心配置文件(1)

1、core.yaml core.yaml配置文件是Peer节点的示例配置文件&#xff0c;具体路径在fabric-samples/config目 录下。该core.yaml示例配置文件共指定了如下六大部分内容。 1.日志部分 日志记录级别有6种&#xff1a; CRITICAL、 ERROR、 WARNING、 NOTICE、 INFO、 DEBUG. …

CUDA矩阵乘法GEMM优化,从全局内存到共享内存优化的详细流程

在​未优化的矩阵乘法​CA*B中&#xff0c;a、b和c分别是指向矩阵 A、B 和 C 的全局内存的指针&#xff1b;blockDim.x、blockDim.y、 和TILE_DIM都等于 w。wxw-thread 块中的每个线程计算 C 的tile中的一个元素&#xff0c;row并且col是由特定线程计算的 C 中元素的行和列。该…

celery----异步任务、延时任务、定时任务

Celery 是一个强大的分布式任务队列&#xff0c;它可以让任务的执行完全脱离主程序&#xff0c;甚至可以被分配到其他主机上运行。我们通常使用它来实现异步任务&#xff08;async task&#xff09;和定时任务&#xff08;crontab&#xff09;。它的架构组成如下图 &#xff1a…

初学帆软踩得坑——数据填报_Excel数据导入

第一次做数据填报&#xff0c;按照教程做完在用excel导入工具本地数据报表的时候出现 1、整块空白合并单元格&#xff0c;数据无法填入的现象 2、表格重新导入一批&#xff0c;无法成功入库&#xff0c;导致只能导入一次&#xff0c;如下图&#xff1a; 说明&#xff1a;点击…

python网络编程(四),用面向对象方式实现文件上传下载

一&#xff1a;背景 在之前已经实现了文件的下载&#xff0c;现在再来完善上传功能&#xff0c;并且使用面向对象来封装&#xff0c;让代码看起来更加清楚明了。 二&#xff1a; 使用规则和运行结果 下载文件&#xff0c;下载格式 get 文件名 get空格后面直接接文件名称&…

MySQL-SQL InnoDB引擎 (下)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xf…

【直播预告】HarmonyOS极客松赋能直播第三期:一次开发多端部署与ArkTS卡片开发

直播预约通道&#xff1a; 【直播预告】HarmonyOS极客松赋能直播第三期&#xff1a;一次开发多端部署与ArkTS卡片开发

朴素模式匹配算法(暴力寻找字串)

目录 0. 前言1. 算法简介2. 代码实现3. 运行结果 0. 前言 使用朴素模式匹配算法查找子串是否位于主串中 开发环境&#xff1a;Dev-Cpp 操作系统&#xff1a;Windows10 专业版 1. 算法简介 朴素模式匹配算法&#xff0c;也称为暴力模式匹配算法或穷举法&#xff0c;是一种简…

自己动手写C语言float浮点数转换字符串的函数

最近在项目中用到了holtek厂商的HT45F24A和BA45F5650两款单片机。 用的开发工具是HT-IDE3000&#xff0c;烧录软件是HOPE3000。 这两款单片机都是8位的单片机&#xff0c;支持寄存器位操作。 HT45F24A单片机不带UART串口&#xff0c;要想实现串口功能&#xff0c;只能自己用定时…

基于肺部图片与文本信息的多模态模型架构

文章题为 「A transformer-based representation learning model with unified processing of multimodal input for clinical diagnostics」 https://www.nature.com/articles/s41551-023-01045-x &#xff08;arXiv版链接: https://arxiv.org/abs/2306.00864&#xff09; htt…

2020年全国硕士研究生入学统一考试管理类专业学位联考数学试题——解析版

2020 级考研管理类联考数学真题 一、问题求解&#xff08;本大题共 15 小题&#xff0c;每小题 3 分&#xff0c;共 45 分&#xff09;下列每题给出 5 个选项中&#xff0c;只有一个是符合要求的&#xff0c;请在答题卡上将所选择的字母涂黑。 1、某产品去年涨价 10%&#xf…

备战2024秋招面试题-Vue的框架原理

前言&#xff1a; \textcolor{Green}{前言&#xff1a;} 前言&#xff1a; &#x1f49e;快秋招了&#xff0c;那么这个专栏就专门来记录一下&#xff0c;同时呢整理一下常见面试题 &#x1f49e;部分题目来自自己的面试题&#xff0c;部分题目来自网络整理 给我冲 学习目标&am…

阿里云服务器ECS介绍_云主机_服务器托管_弹性计算

阿里云服务器安全可靠、弹性可伸缩&#xff0c;CPU可选256核、内存选到3072GB&#xff0c;云服务器ECS规格通用型、计算型、内存型、通用算力型、裸金属、GPU、大数据等ECS实例规格&#xff0c;公网带宽可选到200M&#xff0c;绑定弹性公网EIP带宽可达1000M&#xff0c;共享带宽…

9.外部中断

1.中断概念&#xff1a; &#xff08;1&#xff09;STM32的每个IO口都可以作为外部中断输入&#xff1b; &#xff08;2&#xff09;stm32的中断控制器支持19个外部中断/事件请求 线0~15&#xff1a;对应外部IO口的输入中断&#xff1b;线16&#xff1a;连接到PVD输出&#…

基于jsp+Servlet+mysql的汽车销售系统

基于jspServletmysql的汽车销售系统 一、系统介绍二、功能展示1.项目骨架2.登录界面3.首页4.购物车5.添加车辆6、编辑车辆信息 四、其它1.其他系统实现五.获取源码 一、系统介绍 项目类型&#xff1a;Java web项目 项目名称&#xff1a;基于JSPServlet的汽车销售系统 项目架…

新后端漏洞之----SSRF漏洞(服务端请求伪造)

笔记 前言SSRF漏洞概述SSRF漏洞检测与挖掘SSRF漏洞的回显分类SSRF漏洞利用SSRF漏洞防御 前言 这几天各种技术面试接踵而至&#xff0c;压得我喘不过气了&#xff01;然后面试官问了我这个SSRF漏洞原理和利用方式以及防御手段&#xff0c;当然同时还问了好几个Top10漏洞&#x…