Flask框架的使用

每日一言

(to Komuro Takashi) In a war like this, there is no surrender or shit like that. – Kouta Hirano
from Highschool Of The Dead

安装Flask

python安装库一如既往的简单:

1
pip install Flask

安装完成后输入:

1
pip show Flask

如果显式如下内容就成功安装了flask:

1740574589165

Flask 基本知识

创建一个Flask 应用

创建一个基本的flask应用方法如下:

1
2
3
4
5
6
7
from flask import Flask

app = Flask(__name__)


if __name__ == '__main__':
app.run(debug = True)
  • 首先我们从flask模块中导入Flask类。Flask类是Flask框架的核心,用于创建Flask应用程序实例。
  • app = Flask(__name__) :这行代码创建了一个Flask应用实例。其中传入的参数 __name__ 是python中的一个特殊变量。

若要修改Flask监听的ip地址和端口号,可以在app.run()中传入如下参数:

1
app.run(debug=True,host='0.0.0.0',port=8000)

__name__变量以及Flask()参数的作用

__name__ 变量是python中的一个内置变量。

  • 当python解释器直接运行一个模块时,如 python my_program.py 时,模块的 __name__变量会被设置为字符串:”__main__
  • 当一个模块被其他模块导入时,如 import my_program,该模块的 __name__ 变量会被设置为该模块的文件名(不包含.py后缀),例如:“my_program
__name__传入Flask()的作用

Flask() 使用 __name__ 变量来确定应用的跟路径,从而能够找到应用相关资源的位置。

这意味着:

  • Flask 应用的根目录是以创建 Flask 实例的模块所在的目录为基准的,而不是以当前工作目录为基准
  • 即便你从另一个目录启动 Flask 应用,根路径仍然是创建 Flask 实例的模块所在位置

假设有以下项目目录:

1
2
3
4
/project/
├── app/
│ └── main.py (包含 app = Flask(__name__))
└── run.py (从这里导入并运行 app)

如果在 main.py 中使用 app = Flask(__name__),则:

  • 应用的根路径将是 /project/app/
  • 模板将从 /project/app/templates/ 查找
  • 静态文件将从 /project/app/static/ 查找

即使你从 /project/ 目录运行 python run.py,根路径仍然是 /project/app/

注意:只是Flask应用的根目录为 /project/app/,python的工作目录仍然时你启动的工作目录。

路由

路由是URL路径到python函数的映射关系。Flask 可以通过自定义路由实现当用户访问特定URL时,调用对应的视图****函数来处理请求。

  • 视图函数:视图函数是 Flask 应用中处理特定 URL 请求的函数。当用户访问与某个路由关联的 URL 时,Flask 会调用相应的视图函数来生成响应。这个函数负责执行必要的逻辑,如从数据库获取数据、进行计算、渲染模板等,然后将结果返回给用户。

一组简单的路由和对应的视图函数:

1
2
3
@app.route('/')
def index():
return 'Hello, World!'

请求对象(request)

请求对象是Flask中的一个关键组件,它封装了来自客户端的所有请求信息,并提供了方便的方法和属性来访问这些数据。

需要获取请求对象,首先需要从flask中导入request

1
from flask import Flask, request

每当客户端(如浏览器)向服务器发送请求时,Flask 会自动创建一个 request 对象,并使其在当前请求上下文中可用。

请求对象的主要属性和方法

  • 请求方法和URL

    • request.method - 获取 HTTP 请求方法(GET, POST, PUT, DELETE 等)
    • request.url - 完整的请求 URL
    • request.path - URL 路径部分
    • request.base_url - URL 不带查询参数的部分
    • request.host_url - 只含有主机和协议的 URL 部分
  • 获取请求数据

    • request.args - 获取 URL 查询参数(例如 ?key=value 部分)
    • request.form - 获取表单数据(POST 或 PUT 请求提交的表单)
    • request.values - 结合了 argsform 数据
    • request.files - 获取上传的文件
    • request.json - 获取 JSON 格式的请求主体(当请求头 Content-Type 为 application/json)
    • request.data - 原始请求数据,适用于其他内容类型
  • 请求头和Cookies

    • request.headers - 获取所有请求头
    • request.cookies - 获取请求中的 Cookie
  • 其他常用属性

    • request.environ - 原始 WSGI 环境
    • request.is_secure - 检查是否是 HTTPS 请求
    • request.is_xhr - 检查是否是 AJAX 请求(XMLHttpRequest)
    • request.remote_addr - 客户端 IP 地址

我们简单测试一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from flask import Flask, request
import json

app = Flask(__name__)

@app.route('/')
def hello_world():
# 创建一个字典存储请求信息
request_info = {}
request_info['method'] = request.method
request_info['url'] = request.url
request_info['base_url'] = request.base_url
request_info['path'] = request.path
request_info['args'] = request.args.to_dict()
request_info['request.remote_addr'] = request.remote_addr
return json.dumps(request_info)

if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0',port=8000)

我们访问地址 http://10.29.242.80:8000/?key=123456,看看服务器返回什么:

1
2
3
4
5
6
7
8
{
"method": "GET",
"url": "http://10.29.242.80:8000/?key=123456",
"base_url": "http://10.29.242.80:8000/",
"path": "/",
"args": {"key": "123456"},
"request.remote_addr": "10.29.242.80"
}

响应对象(Response)

在Flask中响应对象是Flask应用向客户端返回数据的一种方式,它封装了服务器向客户端所发送的所有响应信息,包括状态码、响应头和响应体。

最简单的创建一个响应对象的方式就是我们之前见到的视图函数:

1
2
3
@app.route('/')
def index():
return 'Hello, World!' # Flask 会自动将字符串转换为响应对象

Flask 会自动将返回的字符串转换成一个完整的 HTTP 响应,默认状态码为 200 OK,并设置 Content-Type 为 text/html。

可以通过返回参数设置常见的三个响应信息:响应体、响应状态码、响应文本类型

如以上我们测试请求对象时的代码,我们直接返回的虽然是json格式的数据,但是浏览器却以html文本的格式来解析,显式效果如下:
1740665289715

如果我们将返回类型改为:

1
return json.dumps(request_info) , 200, {'Content-Type': 'application/json'}

那么浏览器就会以json数据的格式来解析数据:

1740665367301

使用Response 对象

首先需要从flask中导入response对象:

1
from flask import Flask, Response

使用Response手动创建响应对象:

1
2
3
4
5
6
7
8
9
10
@app.route('/custom')
def custom_response():
content = "<h1>自定义响应</h1>"
response = Response(
response=content, #响应体
status=200, #响应状态码
mimetype="text/html" #响应类型
)
response.headers["自定义头部名"] = "自定义头部值"
return response

返回json对象:

1
2
3
4
5
6
from flask import jsonify	# 注意引头文件

@app.route('/api/data')
def get_data():
data = {"name": "张三", "age": 30}
return jsonify(data) # 自动设置 Content-Type 为 application/json

重定向:

1
2
3
4
5
from flask import redirect, url_for

@app.route('/redirect')
def redirect_example():
return redirect(url_for('hello_world')) # 重定向到 hello_world 路由,注意此处为视图函数名称

设置Cookie:

1
2
3
4
5
@app.route('/set-cookie')
def set_cookie():
response = make_response("Cookie 已设置")
response.set_cookie('username', '张三', max_age=3600) # 一小时后过期
return response

文件下载:

1
2
3
4
5
6
7
8
9
10
11
from flask import send_file, send_from_directory

@app.route('/download')
def download_file():
# 发送文件作为下载
return send_file('static/file.pdf', as_attachment=True)

@app.route('/downloads/<filename>')
def download(filename):
# 从指定目录发送文件
return send_from_directory('downloads', filename, as_attachment=True)

流式响应:(受制于浏览器,可能会等待10秒才会显式)

1
2
3
4
5
6
7
8
@app.route('/stream')
def stream_response():
def generate():
for i in range(10):
yield f"数据块 {i}\n"
time.sleep(1)

return Response(generate(), mimetype='text/plain')

模板

Flask 使用 Jinja2 模板引擎来渲染 HTML 模板。模板允许你将 Python 代码嵌入到 HTML 中,从而动态生成网页。

Flask动态参数路由

Flask支持将url中的部分内容当作动态参数传递给调用的视图函数,如之前文件下载中的路由路径:

1
@app.route('/downloads/<filename>')

其中的 <filename> 就是一个动态参数,当用户访问:/downloads/xxx.png 时,就会将 xxx.png 作为参数 filename传递给调用的视图函数。

还可以指定参数的类型:

  • string:(默认) 接受不包含斜杠的任何文本
  • int:接受正整数
  • float:接受正浮点数
  • path:类似 string,但也接受斜杠
  • uuid:接受 UUID 字符串

例如有如下两个路由:

1
@app.route('/user/<int:user_id>')   # 只匹配整数
1
@app.route('/user/<string:user_name>')  # 只匹配字符串

当我们访问路径 /user/123456 时,会调用第一个路由

当我们访问路径 /user/xxy 时,会调用第二个路由

Jinja2语法

使用双大括号来在文本中嵌入变量的值:

1
2
<p>用户名: {{ username }}</p>
<p>年龄: {{ age }}</p>

控制结构:

控制语句使用语法:

条件语句

1
2
3
4
5
{% if user %}
<h1>你好,{{ user.username }}!</h1>
{% else %}
<h1>请登录</h1>
{% endif %}

循环

1
2
3
4
5
<ul>
{% for item in items %}
<li>{{ item.name }} - {{ item.price }}元</li>
{% endfor %}
</ul>

注释

1
{# 这是一个注释,不会出现在渲染后的HTML中 #} 

蓝图

蓝图(Blueprint)是 Flask 提供的一种组织更大型 Flask 应用的方式,允许你将应用按照功能划分为多个组件或者模块。蓝图可以被视为是应用的子应用,但不是真正独立的应用,它们依赖于应用实例来进行注册。

主要用途

  1. 模块化应用结构 :将大型应用拆分为多个功能模块
  2. 重用视图、模板和静态文件 :不同蓝图可以共享相同的组件
  3. 避免循环导入 :解决大型应用中常见的循环引用问题
  4. 简化路由管理 :每个蓝图可以有自己的路由前缀

会有单独的一篇blog讲解Flask的蓝图,此处先不讲解

Flask中的静态文件

静态文件是指不需要动态生成的内容,如 CSS 样式表、JavaScript 脚本、图片、字体等资源。Flask 提供了一种简单的方式来处理和提供这些静态文件。

静态文件存储位置

1
2
3
4
5
6
7
8
9
/your_app/
├── app.py
└── static/
├── css/
│ └── style.css
├── js/
│ └── script.js
└── images/
└── logo.png

静态文件统一存放在Flask应用目录下的static目录下,可以再使用文件夹对各种静态文件进行分类,也可以直接放在static文件夹下。

访问静态文件

默认情况下,可以直接通过 /static/<filename> 路径来访问静态资源:

如下项目目录时,我们可运行程序后,可以直接访问:http://127.0.0.1:8000/static/test.png

1740750443281

来访问static目录下的test.png图片

url_for()函数

url_for()函数可以根据访问连接动态生成URL。它接受视图函数的名称及任何相关参数,并返回相应的 URL 路径。这个函数是 Flask URL 路由系统的重要组成部分,提供了许多优势和灵活性。

主要参数:

  • 第一个参数 :目标端点名(视图函数的名称/static等)
  • 关键字参数 (根据视图函数自定):路由中的动态部分或查询参数
  • _external=True :生成包含完整域名的绝对 URL
  • _scheme :指定 URL 协议(如 ‘https’)
  • _anchor :添加 URL 片段标识符(锚点)
通过url_for函数访问静态文件

在模板或代码中,推荐使用url_for()函数生成静态文件的url:

1
2
3
4
<!-- 在 HTML 模板中 -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src="{{ url_for('static', filename='js/script.js') }}"></script>
<img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo">
1
2
3
4
# 在 Python 代码中
from flask import url_for

css_url = url_for('static', filename='css/style.css')

flask扩展

Flask 有许多扩展,可以添加额外的功能,如数据库集成、表单验证、用户认证等。这些扩展提供了更高级的功能和第三方集成。

但是flask扩展已经超出flask基础功能的范围,知道可以扩展即可,有需求未来再学习。

错误处理

1
2
3
4
5
6
7
@app.errorhandler(404)
def page_not_found(e):
return 'Page not found', 404

@app.errorhandler(500)
def internal_server_error(e):
return 'Internal server error', 500

Flask框架的使用
http://blog.ulna520.com/2025/02/26/Flask框架的使用_20250226_205249/
Veröffentlicht am
February 26, 2025
Urheberrechtshinweis