详细了解Flask框架的入门

青衣也想佩剑侍 2024-10-25 17:05:02 阅读 57

目录

一、 简介

二、 概要

三、 知识点

1. Flask基础

1)路由route的创建:

2)endpoint的作用

3)request对象的使用

4)请求钩子before/after_request

5)redirect重定向

临时重定向(302)与永久重定向(301)的区别:

6)返回json数据给前端

7)abort函数的使用

8)url_for实现反转

   四、总结     

对于钩子的补充


一、 简介

        Flask 是一个以微核心设计为基础的轻量级 Web 应用框架,它提供了 Web 开发的基础功能,如路由、请求处理和响应构建。这种设计哲学使得 Flask 既简单直观,易于新手上手,又足够灵活,能够满足经验丰富的开发者的需求。开发者可以根据自己的项目需求,选择性地添加各种 Flask 扩展,实现如数据库集成、表单验证等额外功能。

二、 概要

1)安装:Flask 可以通过 Python 的包管理工具 pip 轻松安装,安装命令为

<code>pip install flask

这一步骤是开始使用 Flask 的第一步,确保了开发环境中包含了 Flask 框架及其依赖。

2)组成:Flask 作为一个 WSGI(Web Server Gateway Interface)应用,它的核心组件包括一个开发服务器、调试器和路由系统。这些组件共同构成了 Flask 的基础架构,使得开发者可以快速搭建起一个 Web 应用。

3)模板引擎:Flask 使用 Jinja2 作为其默认的模板引擎,Jinja2 是一个功能强大的模板语言,由 Flask 核心开发者维护,它支持变量替换、循环、条件判断等模板特性,极大地简化了 Web 页面的渲染过程。

4)使用装饰器:Flask 广泛使用 Python 的装饰器模式,这些以 @ 开头的装饰器方法允许开发者以一种非常 Pythonic 的方式扩展或修改函数的行为。在 Flask 中,装饰器被用于路由定义、请求处理、权限验证等多种场景,是 Flask 框架中不可或缺的一部分。

三、 知识点

1. Flask基础
1)路由route的创建:

route装饰器详解

通过创建路由并关联函数,实现一个基本的网页:

from flask import Flask

#导入 Flask 类:首先,代码从 flask 模块导入 Flask 类。

app = Flask(__name__)

#创建 Flask 实例:通过 Flask(__name__) 创建一个 Flask 应用实例。这里的 __name__ 是一个 Python 特殊变量,它代表了当前脚本的名称。Flask 用它来找到资源文件和确定应用程序的根目录。

@app.route("/")

#路由和视图函数:在 Flask 中,路由是将 URL 映射到 Python 函数的过程。@app.route("/") 是一个装饰器,它告诉 Flask 哪个 URL 应该触发哪个函数。在这个例子中,当用户访问应用的根 URL(即网站的首页,通常是 http://localhost:5000/)时,会调用 index 函数。(url 指的是统一资源定位符(Uniform Resource Locator),它是互联网上用来标识资源位置的地址。在 Web 应用中,每个 url 都对应一个特定的页面或资源,浏览器通过向服务器发送请求来获取这些资源。)

def index():

return "Hello World!"

#定义视图函数:index 函数是一个视图函数,它的作用是返回响应给客户端的内容。在这个例子中,当用户访问根 URL 时,index 函数返回字符串 "Hello World!"。

# def not():

# return "Not Hello World!"

#not 函数被注释掉了,这意味着它不会被执行。如果取消注释,它将定义另一个路由,但在这个例子中,我们只关联 index 函数。

app.run()

#启动开发服务器:app.run() 启动 Flask 内置的开发服务器。这个服务器仅用于开发和测试目的,不适用于生产环境。当调用 app.run() 时,服务器会监听来自浏览器的请求,并根据路由规则将请求映射到相应的视图函数。

       选择使用哪种类型的重定向取决于你的具体需求。如果你只是想临时改变资源的位置,使用 302;如果你已经决定永久移动资源,使用 301。

6)返回json数据给前端

       在 Flask 中,返回 JSON 数据给前端是一种常见的做法,用于在服务器和客户端之间传输数据。Flask 提供了 jsonify() 函数,它可以将 Python 字典转换为 JSON 格式的响应。

通过路由的methods指定url允许的请求格式:

     在 Flask 中,methods 参数用于指定一个路由可以响应哪些类型的 HTTP 请求方法。HTTP 请求方法包括但不限于 GET、POST、PUT、DELETE 等,每种方法都有其特定的用途:

    GET 方法通常用于请求服务器发送资源。

    POST 方法通常用于向服务器提交要被处理的数据。

    PUT 方法通常用于更新服务器上的现有资源。

    DELETE 方法通常用于删除服务器上的资源。

from flask import Flask

app = Flask(__name__)

@app.route("/hello",methods=['GET','POST'])

def hello():

return "Hello World!"

#第一个路由 /hello:

#路径:/hello

#允许的请求方法:['GET', 'POST']

#视图函数:hello,当访问 /hello 路径时,无论是 GET 还是 POST 请求,都会调用这个函数,并返回 "Hello World!"。

#methods参数用于指定允许的请求格式

#常规输入url的访问就是get方法

@app.route("/hi",methods=['POST'])

def hi():

return "Hi World!"

#注意路由路径不要重名,映射的视图函数也不要重名

#第二个路由 /hi:

#路径:/hi

#允许的请求方法:['POST']

#视图函数:hi,这个路由只响应 POST 请求,当有 POST 请求访问 /hi 路径时,调用 hi 函数,并返回 "Hi World!"。

app.run()

通过路由在url内添加参数,其关联的函数可以接收该参数:                                                             动态路由:在 Flask 中,可以在路由的 URL 模式中使用尖括号 <...> 来定义动态路由。尖括号内的名称会成为视图函数的参数。                                                                                             类型转换器:Flask 允许你在尖括号内指定类型转换器,这样 URL 中的参数就会被自动转换为相应的类型。例如,<int:id> 表示 id 参数应该是一个整数。Flask 内置了几种类型转换器,如 string(默认,接受任何不包含斜杠的文本)、int(接受正整数)、float(接受正浮点数)、path(接受包含斜杠的文本)等。

from flask import Flask

app = Flask(__name__)

@app.route("/index/<int:id>",)

#定义视图函数:index 函数是一个视图函数,它接收一个名为 id 的参数。这个参数来自于 URL 中的动态部分,并且由于使用了 int 转换器,它会被自动转换为整数类型。

def index(id):

if id == 1:

return 'first'

elif id == 2:

return 'second'

elif id == 3:

return 'thrid'

else:

return 'hello world!'

#条件判断:在 index 函数内部,根据 id 参数的值进行条件判断,返回不同的字符串。例如,如果 id 等于 1,返回 'first';如果 id 等于 2,返回 'second';如果 id 等于 3,返回 'thrid';其他情况返回 'hello world!'。

if __name__=='__main__':

app.run()

##启动应用:if __name__ == '__main__': 这一行检查当前脚本是否作为主程序运行。如果是,执行 app.run() 启动 Flask 应用,使其监听来自客户端的请求。

除了原有的转换器,我们也可以自定义转换器(pip install werkzeug):

from werkzeug.routing import BaseConverter

from flask import Flask

#导入 Flask 和 Werkzeug 模块:首先,代码从 flask 模块导入 Flask 类,用于创建 Flask 应用实例。

#同时,从 werkzeug.routing 导入 BaseConverter 类,用于创建自定义的路由转换器。

app = Flask(__name__)

class RegexConverter(BaseConverter):

#自定义转换器类:定义了一个名为 RegexConverter 的类,它继承自 BaseConverter。这个类用于创建自定义的路由转换器,它可以匹配正则表达式。

def __init__(self,url_map,regex):

super(RegexConverter,self).__init__(url_map)

self.regex = regex

#初始化和定义正则表达式:RegexConverter 类的构造函数接受 url_map 和 regex 两个参数。url_map 是 Flask 应用的 URL 映射,regex 是一个正则表达式字符串,用于定义 URL 模式的匹配规则。

def to_python(self, value):

print('to_python方法被调用')

return value

#实现转换逻辑:to_python 方法是 RegexConverter 类的一个重写方法,用于将 URL 中的值转换为 Python 对象。在这个例子中,它简单地打印一条消息并返回传入的值。

app.url_map.converters['re'] = RegexConverter

#添加自定义转换器到 Flask 应用:通过 app.url_map.converters['re'] = RegexConverter 将自定义的 RegexConverter 类添加到 Flask 应用的 URL 映射中。

#这里的 're' 是转换器的名称,它将在路由定义中使用。

@app.route("/index/<re('1\d{10}'):value>")

#定义路由和视图函数:使用 @app.route() 装饰器定义了一个路由 /index/<re('1\d{10}'):value>。

#这里的 <re('1\d{10}'):value> 是一个动态路由,其中 re 是自定义转换器的名称,'1\d{10}' 是正则表达式,用于匹配以 '1' 开头,后面跟着10位数字的字符串。

def index(value):

print(value)

return "Hello World!"

#视图函数:index 函数是一个视图函数,它接收一个名为 value 的参数,这个参数来自于 URL 中的动态部分,并且已经通过自定义的 RegexConverter 转换器进行了匹配和转换。

if __name__=='__main__':

app.run(debug=True)

2)endpoint的作用

Endpoint 定义:endpoint 是 Flask 应用中的一个字符串标识符,它与一个视图函数关联。当定义路由时,如果不显式指定 endpoint 的名称,Flask 会默认使用视图函数的名称作为 endpoint。每个app中都存在一个url_map

URL 到 Endpoint 的映射:在 Flask 应用的 url_map 中,每个 URL 规则都与一个 endpoint 相关联。这个映射允许 Flask 根据请求的 URL 快速定位到对应的 endpoint。

Endpoint 到视图函数的映射:Flask 应用维护了一个 view_functions 字典,它将 endpoint 映射到对应的视图函数。当 Flask 通过 url_map 找到请求 URL 对应的 endpoint 后,就会在 view_functions 中查找并执行相应的视图函数。

动态路由支持:在定义路由时,可以使用尖括号 <variable_name> 来创建动态 URL 规则。Flask 会根据 URL 中的实际值,将这些变量作为参数传递给视图函数。

请求处理流程:                                                                                                                                 当一个请求到达 Flask 应用时,Flask 首先解析请求的 URL。                                                   Flask 在 url_map 中查找与请求 URL 匹配的规则(rule)。                                                     找到匹配的规则后,Flask 提取对应的 endpoint。                                                                     使用 endpoint,Flask 在 view_functions 中找到并执行相应的视图函数。

from flask import Flask

app = Flask(__name__)

@app.route('/test')

def test():

return 'test success!'

#定义视图函数:test 是一个视图函数,它返回字符串 'test success!'。

#定义路由和默认 endpoint:使用 @app.route('/test') 装饰器将 URL 路径 /test 与 test 视图函数关联。

#在这种情况下,endpoint 默认为视图函数的名称,即 'test'

@app.route('/hello',endpoint='our_set')code>

def hello_world():

return 'Hello World!'

#自定义 endpoint:hello_world 是另一个视图函数,它返回 'Hello World!'。

#使用 @app.route('/hello', endpoint='our_set') 装饰器定义了一个路由,code>

#其中 endpoint='our_set' 显式指定了 endpoint 的名称为 'our_set',而不是使用视图函数的默认名称。code>

if __name__ == '__main__':

print(app.view_functions)

print(app.url_map)

#启动应用前的打印:在 if __name__ == '__main__': 块中,

#首先打印 app.view_functions 和 app.url_map。app.view_functions 是一个字典,它映射 endpoint 到对应的视图函数。

#app.url_map 是一个包含所有 URL 规则的映射,它显示了 URL 规则、endpoint、默认参数等信息。

app.run()

可以通过view_functions查看到当前endpoint与视图函数的对应情况;可以通过url_map查看当前url与endpoint的绑定情况;

# view_functions

{'static': <function Flask.__init__.<locals>.<lambda> at 0x00000230CC2A7DC0>, 'test': <function test at 0x00000230CC30FD30>, 'our_set': <function hello_world at 0x00000230CC30FDC0>}

#view_functions:这是 Flask 应用内部的一个字典,它将每个 endpoint 映射到对应的视图函数。

#我们可以看到三个 endpoint:

#'static':映射到一个匿名函数(lambda 函数),通常用于处理静态文件。

#'test':映射到名为 test 的视图函数。

#'our_set':映射到名为 hello_world 的视图函数,这个 endpoint 是通过 @app.route('/hello', endpoint='our_set') 显式指定的。code>

# url_map

Map([<Rule '/hello' (OPTIONS, HEAD, GET) -> our_set>,

<Rule '/test' (OPTIONS, HEAD, GET) -> test>,

<Rule '/static/<filename>' (OPTIONS, HEAD, GET) -> static>])

#url_map:这是 Flask 应用内部的另一个数据结构,它记录了 URL 规则和它们对应的 endpoint。

#我们可以看到三个 URL 规则:

#'/hello':这个 URL 规则绑定到 'our_set' endpoint,支持 OPTIONS, HEAD, GET 方法。

#'/test':这个 URL 规则绑定到 'test' endpoint,同样支持 OPTIONS, HEAD, GET 方法。

#'/static/<filename>':这是一个处理静态文件的 URL 规则,绑定到 'static' endpoint,也支持 OPTIONS, HEAD, GET 方法。

#以下信息是 Flask 应用启动时的日志输出,提供了应用的运行状态和一些警告信息。

* Serving Flask app 'endpoint_test' (lazy loading)

* Environment: production

WARNING: This is a development server. Do not use it in a production deployment.

Use a production WSGI server instead.

* Debug mode: off

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

#这表示 Flask 应用正在监听本地地址(127.0.0.1)的 5000 端口,等待客户端的请求。

#(Press CTRL+C to quit)" 提示用户可以通过按下 CTRL+C 组合键来停止 Flask 应用的运行。

endpoint相当于给url起一个名字,view_functions内存储的就是url的名字到视图函数的映射,且endpoint在同一个蓝图下也不能重名:

from flask import Flask

app = Flask(__name__)

@app.route('/test',endpoint='Test')code>

#代码定义了一个路由规则,它将 URL 路径 /test 与名为 Test 的 endpoint 关联。

#注意,这里指定的 endpoint 名称是 'Test',而不是视图函数 test 的名称。

def test():

return 'None'

#这是一个视图函数,它被 @app.route 装饰器关联到了 /test 路径,

#但由于我们在装饰器中指定了 endpoint 为 'Test',所以这个函数实际上与 endpoint 'Test' 相关联。

def Test():

return 'World!'

#这是另一个视图函数,它的名称与 endpoint 名称相同,

#但由于 Flask 使用 @app.route 装饰器中的 endpoint 参数来确定映射,所以这个函数实际上并没有被使用。

if __name__ == '__main__':

print(app.view_functions)

print(app.url_map)

app.run()

通过view_functions可以看到,即使修改endpoint为其他视图函数名,依然是绑定其正下方的视图函数,说明endpoint作用于url:

{'static': <function Flask.__init__.<locals>.<lambda> at 0x000002056C378CA0>, 'Test': <function test at 0x000002056C3E0C10>}

#在view_functions 字典中其中包含两个键值对:

#'static' 对应的是一个匿名函数(<function Flask._init_.<locals>.<lambda> at 0x000002056C378CA0>),通常用于处理静态文件相关的请求。

#'Test' 对应的是名为 test 的视图函数(<function test at 0x000002056C3E0C10>)。

#这表示当 Flask 应用接收到与 'static' 或 'Test' 对应的 endpoint 的请求时,会调用相应的函数来处理并生成响应。

3)request对象的使用
在 Flask 框架中,request 对象用于获取客户端发送的请求信息。其中,render_template() 函数可以用于呈现一个我们精心编写的 HTML 文件模板。通过这个函数,能够将动态数据与模板相结合,生成最终的页面返回给用户。另外,request.method 则用于获取 URL 接收到的请求方式,比如常见的 GET、POST 等。根据不同的请求方式,可以返回不同的响应页面,以满足用户的多样化需求。这种根据请求方式进行不同处理的机制,使得应用能够更加灵活地响应用户的操作,提供更优质的服务体验。

#request:包含前端发送过来的所有请求数据

from flask import Flask,render_template,request

app = Flask(__name__)

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

#url映射的函数,要传参则在上述route(路由)中添加参数申明

def index():

if request.method == 'GET':

return render_template('index.html')

#处理 GET 请求:

#if request.method == 'GET'::检查请求方法是否为 GET。

#return render_template('index.html'):如果是 GET 请求,使用 render_template 函数渲染并返回templates 文件夹下的 index.html 模板文件。

#(1、想要html文件被该函数访问到,首先要创建一个templates文件,将html文件放入其中。2、该文件夹需要被标记为模板文件夹,且模板语言设置为jinja2)

# 此处欲发送post请求,需要在对应html文件的form表单中设置method为post

elif request.method == 'POST':

name = request.form.get('name')

password = request.form.get('password')

return name+" "+password

#处理 POST 请求:

#elif request.method == 'POST'::如果请求方法是 POST,则执行此分支。

#name = request.form.get('name') 和 password = request.form.get('password'):从 POST 请求中获取表单数据,这里假设前端表单中有 name 和 password 两个字段。

#return name + " " + password:将获取到的 name 和 password 拼接后返回。

if __name__=='__main__':

app.run()

4)请求钩子before/after_request

       想要在正常执行的代码的前、中、后时期,强行执行一段我们想要执行的功能代码,便要用到钩子函数——用特定装饰器装饰的函数                                                                                下面将介绍Flask内,四种常用的钩子:                                                                                     1、before_request:在每一次请求之前调用;

       该钩子函数表示每一次请求之前,可以执行某个特定功能的函数;

       执行顺序是先绑定的先执行;

       并且先执行 flask app 的 before_request, 再执行 blueprint 的 before_request;

       一般用于检验用户权限、请求是否合法等场景;

from flask import Flask

app = Flask(__name__)

@app.route('/')

def hello_world():

return 'Hello World!'

@app.before_request

def before_request_a():

print('I am in before_request_a')

@app.before_request

def before_request_b():

print('I am in before_request_b')

#定义 before_request 钩子函数:

#@app.before_request:这是一个装饰器,用于标记一个函数,使其在每个请求处理之前执行。

#def before_request_a(): 和 def before_request_b()::分别定义了两个 before_request 钩子函数,它们将按照绑定的顺序执行,即先执行 before_request_a,再执行 before_request_b。

if __name__ == '__main__':

app.run()

# 打印结果

I am in before_request_a

I am in before_request_b

2、before_first_request:与before_request的区别是,只在第一次请求之前调用;                        在 Flask 中,before_request 钩子函数会在每次请求之前执行,                                              而 before_first_request 钩子函数(如果存在)会在应用的生命周期中第一次请求之前执行;                                                                                                                                               执行顺序同样也是先绑定的先执行;

from flask import Flask

app = Flask(__name__)

@app.route('/')

def hello_world():

return 'Hello World!'

@app.before_app_first_request

def before_first_request():

print('This is executed only once, before the first request.')

if __name__ == '__main__':

app.run()

#打印结果

This is executed only once, before the first request.

#在这个示例中:

#当 Flask 应用接收到第一次请求时,before_app_first_request 钩子函数 before_first_request 会被调用,并且只会打印一次 "This is executed only once, before the first request."。

#之后,每次请求都会按照正常的流程处理,但 before_first_request 函数不会再被调用。

#这个钩子非常适合执行一些只需要在应用启动后运行一次的初始化任务,比如数据库迁移、配置缓存等。

3、after_request:每一次请求之后都会调用; 

在 Flask 中,after_request 钩子函数用于在每次请求处理之后执行特定功能,但前提是请求没有抛出未捕获的异常。这些钩子函数可以对响应对象 response 进行操作,比如添加头部信息、修改响应内容等,并且在执行完毕后必须返回 response 对象;

执行的顺序是先绑定的后执行;

被触发的前提是没有异常抛出,或者异常被 errorhandler捕获并处理;

一般可以用于产生csrf_token验证码等场景;        

4、teardown_request:每一次请求之后都会调用;                                                                        该钩子函数接收一个参数,该参数是服务器出现的错误信息;                                                  执行顺序也是先绑定的后执行;                                                                                                  只有在请求上下文被 pop 出请求栈的时候才会直接跳转到teardown_request;                        所以在被正常调用之前,即使某次请求有抛出错误,该请求也都会被继续执行, 并在执行完后返回 response;

from flask import Flask

app = Flask(__name__)

@app.route('/')

def hello_world():

return 'Hello World!'

@app.teardown_request

def teardown_request_a(exc):

if exc:

print(f"Error occurred: {exc}")

else:

print('I am in teardown_request_a. Request completed successfully.')

#使用 @app.teardown_request 装饰器定义了一个钩子函数 teardown_request_a。这个函数会在每次请求结束时被调用,无论请求是否成功。

#exc 参数是一个异常对象,如果请求过程中没有发生异常,exc 将是 None。

@app.teardown_request

def teardown_request_b(exc):

if exc:

print(f"Error occurred: {exc}")

else:

print('I am in teardown_request_b. Request completed successfully.')

#同样使用 @app.teardown_request 装饰器定义了另一个钩子函数 teardown_request_b。这个函数的逻辑与 teardown_request_a 相同,但打印的消息不同。

if __name__ == '__main__':

app.run()

#请求完成后,teardown_request_b 钩子函数首先被调用,然后是 teardown_request_a。这是因为钩子函数的调用顺序是注册顺序的逆序。

#如果请求过程中发生了异常,exc 参数将包含异常信息,钩子函数将打印错误信息。如果没有异常,将打印请求成功完成的消息。

#打印结果

I am in teardown_request_b. Request completed successfully.

I am in teardown_request_a. Request completed successfully.

5)redirect重定向

重定向(Redirect)是 Web 开发中的一个概念,指的是服务器端告诉客户端(通常是浏览器)去请求另一个 URL。这通常用于当网页移动到一个新的地址时,确保用户和搜索引擎仍然能够找到该页面。

在 Flask 框架中,重定向可以通过 flask.redirect() 函数实现。以下是该函数的基本用法:       location: 这是一个必需参数,表示要重定向到的 URL。                                                           code: 这是一个可选参数,表示 HTTP 状态码。默认值是 302,表示临时重定向。你也可以将其设置为 301,表示永久重定向。

from flask import Flask, redirect, url_for

app = Flask(__name__)

@app.route('/')

def index():

return 'This is the index page.'

@app.route('/login')

def login():

# 假设用户登录成功后,重定向到首页

return redirect(url_for('index'))

if __name__ == '__main__':

app.run()

#在这个例子中,如果用户访问 /login 路由,假设他们登录成功,应用将使用 redirect() 函数重定向到首页(/ 路由)。url_for('index') 函数用于生成 index 函数路由的 URL。

临时重定向(302)与永久重定向(301)的区别:
 302 临时重定向:告诉浏览器当前请求的资源暂时位于另一个 URL。搜索引擎在抓取时可能会更新其索引,但用户书签中的 URL 不会改变。                                                                 301 永久重定向:告诉浏览器和搜索引擎当前请求的资源已经永久移动到了新的 URL。这会导致搜索引擎更新其索引,并且用户书签中的 URL 也会更新为新的 URL。方法一:用 make_response 方法和 json 库来返回 JSON 格式的数据

from flask import Flask,make_response,json

app = Flask(__name__)

@app.route("/index")

def index():

data = {

'name':'张三'

}

#使用 @app.route("/index") 装饰器定义了一个路由,当用户访问 /index 时,会调用 index 函数。

#index 函数创建了一个包含中文数据的字典 data。

#(json.dumps 是 Python 标准库 json 模块中的一个函数,用于将 Python 对象(如字典、列表等)序列化为 JSON 格式的字符串。)

#(例如,如果一个 Python 字典 data = {'name': '张三'},使用 json.dumps(data) 将会得到一个类似于 {"name": "张三"} 的 JSON 格式字符串。)

response = make_response(json.dumps(data,ensure_ascii=False))

#使用 json.dumps 方法将字典 data 序列化为 JSON 格式的字符串。

#参数 ensure_ascii=False 允许输出真正的中文字符,而不是使用 ASCII 编码。

#make_response 方法接受 json.dumps 的结果作为参数,创建一个响应对象。

#这个响应对象不是直接返回,而是可以进行更多的后续操作。

response.mimetype = 'application/json'

#设置响应对象的 mimetype 属性为 'application/json',这告诉客户端响应体是 JSON 格式的数据。

#mimetype(MIME 类型)是用于指定数据类型的一种标识。

#在 HTTP 协议中,通过设置 Content-Type 头部的 mimetype 值来告诉客户端(通常是浏览器)接收到的数据的类型。

#在上述代码中,将 response.mimetype 设置为 'application/json' ,

#就是告诉客户端接收到的响应数据是 JSON 格式的,以便客户端能够正确地解析和处理数据。

#常见的 mimetype 还有 'text/html'(HTML 页面)、'text/plain'(纯文本)、'image/jpeg'(JPEG 图片)等。

return response

if __name__=='__main__':

app.run()

#这段代码演示了如何在 Flask 中创建一个路由,当访问该路由时,将 Python 字典序列化为 JSON 格式,

#并设置正确的 MIME 类型,最后将 JSON 数据作为响应返回给客户端。

方法二:用jsonify库实现,减少代码行数                                                                                          jsonify 是 Flask 框架提供的一个函数,主要用于将 Python 数据结构(如字典、列表等)快速转换为符合 JSON 格式的响应,并自动设置正确的 Content-Type 为 application/json

from flask import Flask,jsonify

#首先导入了 Flask 和 jsonify 。

app = Flask(__name__)

app.config['JSON_AS_ASCII'] = False

#设置 app.config['JSON_AS_ASCII'] = False 来确保在将数据转换为 JSON 格式时能够正确处理中文字符。

## 在Flask的config是一个存储了各项配置的字典

# 该操作是进行等效于ensure_ascii=False的配置

@app.route("/index")

#定义了 /index 路由对应的视图函数 index 。在这个函数中,创建了一个包含数据的字典 data 。

def index():

data = {

'name':'张三'

}

return jsonify(data)

#最后,使用 jsonify(data) 直接将 data 字典转换为 JSON 格式的响应并返回。

#jsonify 函数内部完成了数据的序列化以及 Content-Type 的设置,使得代码更加简洁

if __name__=='__main__':

app.run()

运行结果

lask 应用启动并监听默认端口(通常是 5000)。当访问 <code>/index 路由时,index 视图函数被触发。index 函数创建了一个包含中文字符的字典 data。使用 jsonify(data) 将字典转换为 JSON 格式的字符串,并设置响应的 Content-Type 为 application/json。由于设置了 app.config['JSON_AS_ASCII'] = False,JSON 字符串中的中文字符将被正确编码,而不是使用 ASCII 编码。jsonify 函数返回的是一个响应对象,该对象包含了 JSON 格式的数据和正确的 Content-Type 头部。Flask 将这个响应对象发送给客户端(例如,浏览器或 API 测试工具如 Postman)。

7)abort函数的使用

abort() 是 Flask 中的一个函数,它用于立即终止请求并返回一个错误响应。这类似于 Python 中的 raise 语句,因为它可以抛出一个异常来中断正常的执行流程。abort() 函数通常用于以下几种情况:                                                                                                                                     验证失败:当用户提交的数据不符合预期格式或验证规则时,可以使用 abort() 来返回一个错误响应。                                                                                                                                     资源未找到:如果请求的资源不存在,可以使用 abort() 抛出一个 404 错误。                         权限不足:当用户尝试访问他们没有权限的资源时,可以使用 abort() 返回一个 403 错误。                                                                                                                                                   服务器错误:在发生服务器错误时,可以使用 abort() 返回一个 500 错误。          abort() 函数可以接收一个参数,这个参数是一个 HTTP 状态码,表示要返回的错误类型。Flask 还提供了一些快捷方式来抛出常见的 HTTP 错误,例如 abort(404) 表示资源未找到,abort(403) 表示禁止访问。使用类似于python中的raise函数,可以在需要退出请求的地方抛出错误,并结束该请求;                在 Python 中,`raise` 函数用于主动抛出异常。异常是一种特殊的情况,表示程序在运行时遇到了错误或不正常的情况。 通过使用 `raise` ,您可以自定义异常类型和相关的错误信息,以中断程序的正常执行流程,并将控制权转移到能够处理该异常的代码部分(通常是异常处理程序)。 例如:

def divide_numbers(a, b):

if b == 0:

raise ValueError("除数不能为 0")

return a / b

try:

result = divide_numbers(5, 0)

except ValueError as e:

print(e) 在上述示例中,定义了一个 `divide_numbers` 函数,如果除数 `b` 为 0 ,就使用 `raise ValueError("除数不能为 0")` 抛出一个值错误异常。在调用这个函数的部分,使用 `try-except` 结构来捕获并处理这个异常。我们可以使用errorhandler()装饰器来进行异常的捕获与自定义:

from flask import Flask,render_template,request,abort

app = Flask(__name__)

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

def index():

if request.method == 'GET':

return render_template('index.html')

elif request.method == 'POST':

name = request.form.get('name')

password = request.form.get('password')

if name == 'zhangsan' and password == '123456':

return 'login sucess'

else:

# abort的用法类似于python中的raise,在网页中主动抛出错误

abort(404)

return None

#对于 POST 请求,从表单中获取 name 和 password,如果用户名和密码匹配(在这个例子中是 zhangsan 和 123456),则返回登录成功的信息。

#如果不匹配,使用 abort(404) 抛出一个 404 错误。

#使用 abort() 抛出错误:abort(404) 的作用类似于 Python 中的 raise 语句,它立即终止当前请求并抛出一个 HTTP 404 错误。

#在 Flask 中,abort() 函数用于快速返回一个错误响应。

@app.errorhandler(404)

#使用 @app.errorhandler(404) 装饰器定义了一个错误处理函数 handle_404_error,

#用于捕获并自定义 404 错误页面。当 Flask 应用抛出 404 错误时,会自动调用这个函数。

def handle_404_error(err):

# return "发生了错误,错误情况是:%s"%err

# 自定义一个界面

return render_template('404.html')

#handle_404_error 函数接收一个参数 err,这是错误对象。

#在这个函数中,可以选择返回一个自定义的错误信息或者渲染一个错误页面。

#在这个例子中,它渲染了 404.html 模板。

if __name__ == '__main__':

app.run()

#这段代码演示了如何在 Flask 应用中使用 abort() 来抛出错误,并使用 errorhandler() 装饰器来捕获和自定义错误页面。

#这样,当发生错误时,用户会看到一个友好的错误提示,而不是默认的或者不友好的错误页面。

自定义的404界面:

<!DOCTYPE html>

<html lang="en">code>

<head>

<meta charset="UTF-8">code>

<title>404 - 页面未找到</title>

<style>

body {

font-family: Arial, sans-serif;

background-color: #f8f9fa;

text-align: center;

padding: 50px;

}

h1 {

color: #dc3545;

font-size: 48px;

}

p {

color: #6c757d;

font-size: 20px;

}

</style>

</head>

<body>

<h1>404</h1>

<p>抱歉,您所请求的页面未找到!</p>

</body>

</html>

8)url_for实现反转

“url_for 是实现 url 反转的工具,即视图函数 → url”:

url_for 函数的主要作用是根据给定的视图函数或端点(endpoint)生成相应的 URL 地址。这意味着您不必手动记住和编写每个视图函数对应的具体 URL 路径,而是通过提供视图函数的相关信息来自动获取正确的 URL 。

“静态文件引入:url_for('static', filename='文件路径') ,静态文件需要存储在当前工程下的 static 目录内”:

当需要在模板或代码中引入静态文件(如 CSS 文件、JavaScript 文件、图片等)时,可以使用 <code>url_for('static', filename='文件路径')code> 。'static' 是一个固定的名称,表示要获取静态文件的 URL 。filename 是要引入的具体文件的路径,相对于 static 目录。例如,如果有一个图片 image.jpg 位于 static/images 目录下,那么 filename 应该设置为 'images/image.jpg' 。要求将静态文件存储在 static 目录内,是为了让 Flask 能够按照约定的规则正确找到和处理这些文件。

“定义路由:url_for('模块名.视图名',变量=参数)”:

这里说明了 url_for 函数的调用方式,第一个参数用于指定要反转 URL 的视图。如果是在多模块的程序中,或者使用了蓝图(Blueprint),需要明确指定模块名和视图名,以确保准确找到对应的视图。后面的变量和参数部分用于传递动态参数给视图函数,从而生成包含正确参数的 URL 。

“参数一中的视图名实质指的是 endpoint,url_map 中存储了 url 到 endpoint 的映射,只是默认情况下 endpoint 与视图函数名相同”:

在 Flask 中,每个视图函数都有一个对应的 endpoint 。默认情况下,endpoint 的名称与视图函数的名称相同,但您也可以在定义路由时通过某些方式(如在装饰器中)自定义 endpoint 。url_map 是 Flask 内部用于存储 URL 与 endpoint 之间映射关系的数据结构。当使用 url_for 时,它会根据提供的 endpoint 在 url_map 中查找对应的 URL 。

“如果在装饰器中修改了 endpoint,则 url_for 只能使用 endpoint 设置的名字来反转 url”:

如果您在定义视图函数的装饰器中明确修改了 endpoint 的名称,那么在使用 url_for 生成 URL 时,就必须使用修改后的 endpoint 名称,否则无法正确获取到对应的 URL 。

“在单模块程序下我们可以省略模块名,但当使用了蓝图(Blueprint)后,参数一就必须使用‘蓝图模块名.视图名’,因为不同蓝图下的视图函数可以重名”:

在简单的单模块程序中,如果没有使用蓝图,并且视图函数的名称是唯一的,那么在调用 url_for 时可以省略模块名,直接使用视图函数名或 endpoint 。蓝图是一种将应用分割为多个子模块的方式,不同蓝图中的视图函数可能具有相同的名称。为了区分和准确获取特定蓝图中的视图的 URL ,就必须在 url_for 的第一个参数中明确指定“蓝图模块名.视图名”的形式。

   四、总结     

Flask 是一个轻量级的 Web 应用框架,它以微核心设计为基础,提供了 Web 开发的基础功能,包括路由、请求处理和响应构建。Flask 的设计哲学既简单直观,易于新手上手,又足够灵活,能够满足经验丰富的开发者的需求。开发者可以根据自己的项目需求添加各种 Flask 扩展,实现数据库集成、表单验证等额外功能。

Flask 通过使用装饰器模式简化了路由和视图函数的创建,支持动态路由和类型转换器,允许开发者定义灵活的 URL 模式。它内置了对请求钩子的支持,如 before_requestafter_request 和 teardown_request,使得应用能够在请求的不同阶段执行特定的操作。此外,Flask 提供了 jsonify 函数和 abort 函数,分别用于返回 JSON 数据和处理错误情况。

Flask 的 url_for 函数是实现 URL 反转的关键工具,它可以根据视图函数或端点名称生成相应的 URL。这使得 URL 管理更加自动化和减少错误。在多模块或使用蓝图的情况下,url_for 需要明确指定模块名和视图名以确保正确解析 URL。Flask 的错误处理机制允许开发者通过 errorhandler 装饰器自定义错误页面,提供更友好的用户体验。

对于钩子的补充

       在 Flask 中,before_request 钩子函数可以在应用级别和蓝图(Blueprint)级别定义。蓝图是 Flask 提供的一种组织视图函数的方式,允许在不同的模块中定义一组相关的视图,然后将它们注册到主 Flask 应用中。

       当在 Flask 应用和蓝图中都定义了 before_request 钩子函数时,它们的执行顺序如下:

先执行 Flask 应用的 before_request

    这意味着,首先会执行在主 Flask 应用上注册的 before_request 钩子函数。

再执行蓝图的 before_request

    接下来,会执行在蓝图上注册的 before_request 钩子函数。

例如,假设有以下代码结构:

from flask import Flask

app = Flask(__name__)

@app.before_request

def app_before_request():

print('App before request')

def make_blueprint():

from flask import Blueprint

bp = Blueprint('bp', __name__)

@bp.before_request

def bp_before_request():

print('Blueprint before request')

return bp

# 注册蓝图

app.register_blueprint(make_blueprint())

      在这个例子中,app_before_request 是在主 Flask 应用上注册的 before_request 钩子函数,而 bp_before_request 是在一个蓝图上注册的 before_request 钩子函数。当您访问注册到该蓝图的路由时,控制台将首先打印出 "App before request",然后打印出 "Blueprint before request"。           这种机制允许您在请求处理的不同阶段执行不同的初始化或验证逻辑,同时保持代码的模块化和组织性。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。