Flask诞生于2010年,是用Python语言,基于Werkzeug工具箱编写的轻量级、灵活的Web开发框架,非常适合初学者或小型到中型的 Web 项目。
Flask本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login),都需要用第三方的扩展来实现。其 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2。这两个也是Flask框架的核心。
Python最出名的框架要数Django,此外还有Flask、Tornado等框架。虽然Flask不是最出名的框架,但是Flask应该算是最灵活的框架之一,这也是Flask受到广大开发者喜爱的原因。
pip install flask
路由是Web应用中访问不同页面的方式。在Flask中,我们可以通过定义不同的路由来实现不同页面的访问。
处理函数和和URL的关系,Flask通过修饰器把函数注册为路由。访问http://localhost:5000就会调用index这个视图函数
访问:http://127.0.0.1:5000,页面即可得到hello world.
在app对象上定义路由的方式如下:
@app.route('/')
def index():
return 'Hello World!'
这个路由将会匹配根目录,并返回一个"Hello World!"的字符串。
变量规则
要给URL添加变量部分,可以把特殊字段标记为
,这部分将会作为命令参数传递到函数。
构造URL
在Web程序中常常需要获取某个页面的URL,在Flask中需要使用url_for(‘方法名’)来构造对应方法的URL。
模板是Web应用中将数据呈现给用户的一种方式。在Flask中,我使用Jinja2模板引擎来渲染模板。
Jinja2 是一个 Python 模板引擎,主要用于在应用程序中生成动态内容。它由 Armin Ronacher 创建,是 Flask Web 框架默认使用的模板引擎,也广泛用于其他 Python Web 框架和项目中。
Flask默认使用Jinja2作为模板,Flask会自动配置Jinja 模板,默认情况下,模板文件需要放在templates文件夹下。
Jinja 模板和其他语言和框架的模板类似,都是通过语法将HTML文件中的特定元素替换为实际的值。类似java的JSP等模板。从下面的例子中我们应该可以看到Jinja 模板的基本语法了。代码块需要包含在{% %}块中。
使用 Jinja 模板,只需要使用render_template函数并传入模板文件名和参数名即可。
在 Flask 中,app.run()
方法用于运行应用的开发服务器。默认情况下,app.run()
使用的是 Werkzeug 服务器,并且只会在本地主机(127.0.0.1)上监听端口 5000。具体的默认参数如下:
app.run(
host="127.0.0.1", # 监听的主机地址
port=5000, # 监听的端口号
debug=False, # 是否启用调试模式
load_dotenv=True, # 是否加载 .env 文件
**options # 其他选项,例如 ssl_context 等
)
如果你在应用的代码中只是简单地调用 app.run()
而没有传递参数,那么默认情况下应用会在本地主机的端口 5000 上运行,并且不启用调试模式。这通常用于在开发阶段进行测试和调试。
创建一个 Python 文件(例如 app.py
)来定义你的 Flask 应用:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return 'Hello, Flask!'
在这个例子中,我们创建了一个名为 app
的 Flask 应用,并定义了一个简单的路由 /
,该路由返回 “Hello, Flask!”。
运行 Flask 应用
在命令行中运行以下命令启动 Flask 应用:
python app.py
你将看到输出类似于以下内容:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Flask 应用默认在 http://127.0.0.1:5000/
上运行。在浏览器中打开这个地址,你将看到 “Hello, Flask!”。
以Flask与APScheduler构建简易任务监控应用为例,创建更多复杂的路由,并使用模板引擎(例如 Jinja2)来渲染 HTML 页面。以下是一个简单的示例:
import pytz
from apscheduler.schedulers.background import BackgroundScheduler
import datetime
import sys
import os
from flask import Flask, render_template
from loguru import logger
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
from PVSystem.PVAPScheduler import get_weather_data as get_weather24_data
from PVSystem.PVAPScheduler import monitor_data
from PVSystem.qweatherToDB import get_weather_data
from PVSystem.PVPowerForecastToDB import get_power_data
from PVSystem.PVForecastAPScheduler import set_pv_forecast
from PVSystem.PVTrainAPScheduler import get_weather_data as get_now_weather
logger.add("PVAPScheduler_{time}.log")
hms_dict = [{'fun':get_weather24_data,'id':'get_weather24_data','hour':None,'minute':'00','second':'20','trigger':'cron'},
{'fun':monitor_data,'id':'monitor_data','hour':None,'minute':'00','second':'40','trigger':'cron'},
{'fun':get_weather_data,'id':'get_weather_data','hour':'00','minute':'10','second':'00','trigger':'cron'},
{'fun':set_pv_forecast,'id':'set_pv_forecast','hour':'00','minute':'13','second':'30','trigger':'cron'},
{'fun':get_power_data,'id':'get_power_data','hour':'00','minute':'15','second':'00','trigger':'cron'},
{'fun':get_now_weather,'id':'get_now_weather','hour':None,'minute':'05','second':'00','trigger':'cron'},]
app = Flask(__name__)
scheduler = BackgroundScheduler(timezone=pytz.timezone("Asia/Shanghai") )
@app.route('/')
def home():
return 'Hello, Flask!'
@app.route('/task_list')
def task_list():
jobs = scheduler.get_jobs()
return render_template('task_list.html', jobs=jobs)
if __name__ == "__main__":
# 添加任务到调度器
for v in hms_dict:
scheduler.add_job(v['fun'], v['trigger'],hour=v['hour'],minute = v['minute'], second=v['second'], misfire_grace_time=120,id=v['id'])
# 启动 Flask 应用和调度器
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
pass
# 启动 Flask 应用
app.run(port=5002)
在这个例子中,我们定义了一个路由 /task_list
,并使用 render_template
渲染一个包含参数的 HTML 页面。
在项目的根目录下创建一个名为 templates
的文件夹,并在其中创建模板文件,例如 task_list.html
:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Task Listtitle>
<style>
table {
width: 50%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
style>
head>
<body>
<h1>Task Listh1>
<table>
<thead>
<tr>
<th>任务名称th>
<th>下次开始执行时间th>
tr>
thead>
<tbody>
{% for job in jobs %}
<tr>
<td>{{ job.id }}td>
<td>{{ job.next_run_time }}td>
tr>
{% endfor %}
tbody>
table>
body>
html>
这是一个简单的 HTML 模板,在这个模板中,我们使用 Jinja2 模板引擎来循环显示任务列表中的任务 ID 和下次运行时间,使用了 Jinja2 的模板语法。
重新运行应用:
python app.py
在浏览器中访问 `http://127.0.0.1:5002/task_list。
这只是一个 Flask Web 开发的简单入门,Flask 提供了更多功能,例如数据库集成、表单处理、用户认证等,可以根据项目需求逐步学习和使用。
使用 WSGI(Web Server Gateway Interface)服务器是在生产环境中部署 Flask 应用的推荐做法。WSGI 是一种标准的接口,用于定义 Web 服务器和 Python Web 应用程序之间的通信协议。通过使用专业的 WSGI 服务器,可以提高性能、可靠性和安全性。
安装 Gunicorn
pip install gunicorn
启动 Flask 应用
在命令行中执行以下命令,使用 Gunicorn 启动应用:
gunicorn -w 4 -b 0.0.0.0:5000 run:app
-w 4
: 指定启动 4 个工作进程。可以根据需要调整工作进程的数量。-b 0.0.0.0:5000
: 指定服务器监听的地址和端口。run:app
: 指定运行的模块和应用对象。这个命令告诉 Gunicorn 启动应用,监听指定的地址和端口,并使用指定数量的工作进程来处理请求。
访问 http://127.0.0.1:5000/
,确保应用在 Gunicorn 下正常运行。你将不再看到 Flask 的调试信息,而是 Gunicorn 提供的日志信息。
这样,你就成功地用 Gunicorn 作为 WSGI 服务器来运行 Flask 应用。在生产环境中,可以使用类似 Nginx 或 Apache 作为反向代理,将请求转发给 Gunicorn 处理,以提供更好的性能和可扩展性。
APScheduler提供了BackgroundScheduler和BlockingScheduler两种类型的调度器,用于创建定时任务。
这里使用非阻塞BackgroundScheduler,如上文代码。
scheduler = BackgroundScheduler(timezone=pytz.timezone("Asia/Shanghai") )
并且定义为全局变量。
Flask常用扩展包:
参考:
一抹浅笑. Python之flask框架. 博客园. 2019.01
我还可以熬_. Flask之jinja2模板(一). CSDN博客. 2022.10
黑马程序员Python. 如何最简单、通俗地理解Flask?. 知乎. 2022.09
范高伦. Flask框架. CSDN博客. 2019.10