Python Flask框架核心功能与实战指南
本文详细解析Python Flask微框架的核心功能,涵盖环境安装、调试模式开启、路由与路径变量定义、URL构造、HTTP方法处理、静态文件与模板渲染,以及请求参数、文件上传、Session管理和错误处理等关键实战技巧,帮助开发者快速构建Web应用。
Flask是一个基于Python编写的轻量级Web微框架,旨在帮助开发者利用Python语言快速构建网站或Web服务。本文内容主要参考Flask官方文档,其中大部分代码示例直接引用自官方文档。
安装flask
首先进行Flask的安装,最简单且推荐的方式是使用pip工具。
pip install flask接下来,创建一个Python文件并输入以下代码后运行该文件。随后在浏览器中访问localhost:5000,即可看到页面上输出了hello world。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
if __name__ == '__main__':
app.run(host='127.0.0.1',port=5000)调试模式
修改代码中的输出内容后,若直接刷新浏览器,通常不会看到任何变化。实际上,Flask内置了调试模式,支持代码自动重载及显示调试信息。开启该模式的方法十分简单,只需设置FLASK_DEBUG环境变量,并将其值设为1。此外,也可以通过设置app.debug=True来实现。
from flask import Flask
app = Flask(__name__)
app.debug=True
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/login')
def login():
return 'Login'
if __name__ == '__main__':
app.run()再次运行程序后,终端会输出类似如下信息。此时若再次修改代码,Flask会自动重启服务以应用更改。
* Restarting with stat * Debugger is active! * Debugger PIN: 157-063-180 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
路由
在上述示例中可以看到路由的基本用法。若熟悉Spring Web MVC,会对路由概念感到熟悉。在Flask中,路由通过app.route装饰器进行设置,其作用类似于Java中的注解。
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello, World'路径变量
若希望获取/article/1这类包含动态参数的路径,需使用路径变量。路径变量的语法格式为/path/<converter:varname>。在路径变量前,还可以添加可选的转换器,常见的转换器包括以下几种。
| 转换器 | 作用 |
|---|---|
| string | 默认选项,接受除了斜杠之外的字符串 |
| int | 接受整数 |
| float | 接受浮点数 |
| path | 和string类似,不过可以接受带斜杠的字符串 |
| any | 匹配任何一种转换器 |
| uuid | 接受UUID字符串 |
以下是Flask官方提供的示例代码。
@app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return 'User %s' % username
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id构造URL
在Web开发中,经常需要获取特定页面的URL。在Flask中,需使用url_for('方法名')来构造对应视图函数的URL。下面是Flask官方提供的示例。
>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
...
>>> @app.route('/login')
... def login(): pass
...
>>> @app.route('/user/<username>')
... def profile(username): pass
...
>>> with app.test_request_context():
... print url_for('index')
... print url_for('login')
... print url_for('login', next='/')
... print url_for('profile', username='John Doe')
...
/
/login
/login?next=/
/user/John%20Doe
HTTP方法
若需处理特定的HTTP请求方法,在Flask中同样简单,只需在route装饰器中通过methods参数指定即可。
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()静态文件
Web程序通常需要处理静态资源,在Flask中需使用url_for函数,并指定static端点名及文件名。在下面的示例中,实际的文件应放置在static/文件夹下。
url_for('static', filename='style.css')模板生成
Flask默认采用Jinja2作为模板引擎,并会自动配置Jinja模板,因此无需额外配置。默认情况下,模板文件需放置在templates文件夹下。
使用Jinja模板时,只需调用render_template函数,并传入模板文件名及参数即可。
from flask import render_template
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)相应的模板文件内容如下所示。
<!doctype html>
<title>Hello from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello, World!</h1>
{% endif %}日志输出
Flask预配置了一个Logger对象,我们可直接在程序中使用。该Logger是一个标准的Python Logger,因此可以按照标准Logger的方式进行配置,详细信息可参考官方文档或相关Python日志输出文章。
app.logger.debug('A value for debugging') app.logger.warning('A warning occurred (%d apples)', 42) app.logger.error('An error occurred')
处理请求
在Flask中获取请求参数需使用request等全局对象,但这些对象较为特殊,属于Context Locals(上下文局部变量代理)。尽管在代码中表现为全局变量,但在每个请求的作用域内,它们都是相互独立的变量。理解这一点后,后续操作将变得非常简单。
Request 对象
Request对象是一个全局可用对象,利用其属性和方法,可以方便地获取从页面传递过来的参数。
method属性会返回HTTP方法的字符串表示,例如post和get。form属性是一个字典,若数据通过POST类型的表单提交,即可从form属性中获取。下面是Flask官方提供的示例,演示了Request对象的method和form属性用法。
from flask import request
@app.route('/login', methods=['POST', 'GET'])
def login():
error = None
if request.method == 'POST':
if valid_login(request.form['username'],
request.form['password']):
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username/password'
# the code below is executed if the request method
# was GET or the credentials were invalid
return render_template('login.html', error=error)若数据通过GET方法传送,可使用args属性获取,该属性同样是一个字典。
searchword = request.args.get('key', '')文件上传
利用Flask可以方便地获取表单中上传的文件,只需利用request对象的files属性即可,该属性是一个字典,包含了被上传的文件信息。若需获取上传的文件名,可使用filename属性,但需注意该属性可能被客户端篡改,因此并不可靠。更稳妥的办法是利用werkzeug提供的secure_filename方法来获取安全的文件名。
from flask import request
from werkzeug.utils import secure_filename
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/' + secure_filename(f.filename))Cookies
Flask也能便捷地处理Cookie。使用方法十分简单,直接参考官方示例即可。以下示例展示了如何获取Cookie。
from flask import request
@app.route('/')
def index():
username = request.cookies.get('username')
# 使用 cookies.get(key) 代替 cookies[key] 避免
# 得到 KeyError 如果cookie不存在若需向客户端发送Cookie,可参考以下示例。
from flask import make_response
@app.route('/')
def index():
resp = make_response(render_template(...))
resp.set_cookie('username', 'the username')
return resp重定向和错误
redirect和abort函数分别用于实现重定向和返回错误页面。
from flask import abort, redirect, url_for
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/login')
def login():
abort(401)
this_is_never_executed()默认的错误页面是一个空白页面,若需自定义错误页面,可使用errorhandler装饰器。
from flask import render_template
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'), 404响应处理
默认情况下,Flask会根据函数的返回值自动决定响应处理方式:若返回值是响应对象,则直接传递给客户端;若返回值是字符串,则将其转换为合适的响应对象。我们也可以自行决定如何设置响应对象,方法很简单,使用make_response函数即可。
@app.errorhandler(404)
def not_found(error):
resp = make_response(render_template('error.html'), 404)
resp.headers['X-Something'] = 'A value'
return respSessions
我们可以使用全局对象session来管理用户会话。Session建立在Cookie技术之上,但在Flask中,我们还可以为Session指定密钥,这样存储在Cookie中的信息就会被加密,从而更加安全。直接参考Flask官方示例即可。
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
@app.route('/')
def index():
if 'username' in session:
return 'Logged in as %s' % escape(session['username'])
return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form method="post">
<p><input type=text name=username>
<p><input type=submit value=Login>
</form>
'''
@app.route('/logout')
def logout():
# remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('index'))
# set the secret key. keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'模板简介
此处简要介绍Jinja模板的使用方法,更详细的资料请直接查阅官方文档。
模板标签
Jinja模板与其他语言和框架的模板类似,本质上都是通过特定语法将HTML文件中的特定元素替换为实际值。若使用过JSP、Thymeleaf等模板,应能轻松掌握Jinja模板的使用。
从上述示例中,我们应已看到Jinja模板的基本语法。代码块需包含在{% %}块中,例如以下代码所示。
{% extends 'layout.html' %}
{% block title %}主页{% endblock %}
{% block body %}
<div class="jumbotron">
<h1>主页</h1>
</div>
{% endblock %}双大括号中的内容不会被转义,所有内容均原样输出,它常与其他辅助函数配合使用。以下是一个示例。
<a class="navbar-brand" href={{ url_for('index') }}>Flask小例子</a>
继承
模板支持继承其他模板,我们可以将布局设置为父模板,让其他模板继承,从而非常方便地控制整个程序的外观。
例如,这里有一个layout.html模板,它是整个程序的布局文件。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static',filename='css/bootstrap.css') }}" rel="external nofollow" />
<link rel="stylesheet" href="{{ url_for('static',filename='css/bootstrap-theme.css') }}" rel="external nofollow" />
</head>
<body>
<div class="container body-content">
{% block body %}{% endblock %}
</div>
<div class="container footer">
<hr>
<p>这是页脚</p>
<script src="{{ url_for('static',filename='js/jquery.js') }}"></script>
<script src="{{ url_for('static',filename='js/bootstrap.js') }}"></script>
</body>
</html>其他模板可如此编写。对比面向对象编程中的继承概念,我们可以很容易地理解这一机制。
{% extends 'layout.html' %}
{% block title %}主页{% endblock %}
{% block body %}
<div class="jumbotron">
<h1>主页</h1>
<p>本项目演示了Flask的简单使用方法,点击导航栏上的菜单条查看具体功能。</p>
</div>
{% endblock %}控制流
条件判断可如此编写,类似于JSP标签中的Java代码,{% %}中也可以编写Python代码。以下是Flask官方文档提供的示例。
<div class=metanav>
{% if not session.logged_in %}
<a href="{{ url_for('login') }}" rel="external nofollow" >log in</a>
{% else %}
<a href="{{ url_for('logout') }}" rel="external nofollow" >log out</a>
{% endif %}
</div>循环语句可如此编写,与在Python中遍历列表的方式相似。
<tbody>
{% for key,value in data.items() %}
<tr>
<td>{{ key }}</td>
<td>{{ value }}</td>
</tr>
{% endfor %}
<tr>
<td>文件</td>
<td></td>
</tr>
</tbody>需注意,并非所有Python代码都可以直接写在模板里。若希望从模板中引用其他文件的函数,需显式将函数注册到模板中。可参考Stack Overflow上的相关提问。
写在最后
本文主要参考了Flask的官方文档,但仅介绍了Flask最基本的一部分内容。掌握这部分知识后,我们可以用Python搭建一个小服务器来做些事情。若希望详细了解Flask的用法,请关注更详细的资料。本文旨在起到抛砖引玉的作用。
顺便提及,通过Flask我也体会到了Python语言的执行速度。众所周知,编译器编译后的代码执行速度比解释器解释执行的代码快几十倍到几千倍不等。以前学习Java时,感觉Java较慢,主要原因之一是等待编译时间较长。相对而言,用Python写脚本则很快,因为没有编译过程。
但从Flask的运行速度来看,我切身感受到了Python执行确实不快。举个例子,在Spring中编写一个控制器,接收HTTP参数并显示到页面上,若程序编译完成后,这个显示过程基本是瞬时的。但同样的需求在Flask中,我居然能感觉到明显的延迟(大约几百毫秒的等待时间)。因此,如果你想编写一个速度较快的Web程序,还是建议使用Java或JVM语言,虽然看似传统,但性能确实出色。
到此这篇关于Python中的flask框架详解的文章就介绍到这了,更多相关Python flask框架内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













