优秀的编程知识分享平台

网站首页 > 技术文章 正文

04. Flask的基础用法之三(flask wgsi)

nanyue 2024-10-15 11:34:15 技术文章 4 ℃

七、渲染模板

在 Python 内部生成 HTML 好玩,但相当笨拙,你必须自己负责 HTML 转义, 以确保应用的安全。因此, Flask 自动为你配置 Jinja2 模板引擎。

使用 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)

Flask 会在 templates 文件夹内寻找模板。因此,如果你的应用是一个模块, 那么模板文件夹应该在模块旁边;如果是一个包,那么就应该在包里面:

情形 1 : 一个模块:

/application.py

/templates

/hello.html

情形 2 : 一个包:

/application

/__init__.py

/templates

/hello.html

你可以充分使用 Jinja2 模板引擎的威力。更多内容,详见官方 Jinja2 模板文档 。

模板示例:

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
 <h1>Hello {{ name }}!</h1>
{% else %}
 <h1>Hello, World!</h1>
{% endif %}

在模板内部可以和访问 get_flashed_messages() 函数一样访问 request 、 session 和 g [1] 对象。

模板在继承使用的情况下尤其有用。其工作原理参见 模板继承 方案文档。简单的说,模板继承可以使每个页面的特定元素(如页头、导航和页尾) 保持一致。

自动转义默认开启。因此,如果 name 包含 HTML ,那么会被自动转义。如果你可以 信任某个变量,且知道它是安全的 HTML (例如变量来自一个把 wiki 标记转换为 HTML 的模块),那么可以使用 Markup 类把它标记为安全的,或者在模板 中使用 |safe 过滤器。更多例子参见 Jinja 2 文档。

下面 Markup 类的基本使用方法:

>>> from flask import Markup

>>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'

Markup(u'<strong>Hello <blink>hacker</blink>!</strong>')

>>> Markup.escape('<blink>hacker</blink>')

Markup(u'<blink>hacker</blink>')

>>> Markup('<em>Marked up</em> ? HTML').striptags()

u'Marked up \xbb HTML'

八、操作请求数据

对于 web 应用来说对客户端向服务器发送的数据作出响应很重要。在 Flask 中由全局 对象 request 来提供请求信息。如果你有一些 Python 基础,那么 可能 会奇怪:既然这个对象是全局的,怎么还能保持线程安全?答案是本地环境:

九、本地环境

某些对象在 Flask 中是全局对象,但不是通常意义下的全局对象。这些对象实际上是 特定环境下本地对象的代理。真拗口!但还是很容易理解的。

设想现在处于处理线程的环境中。一个请求进来了,服务器决定生成一个新线程(或者 叫其他什么名称的东西,这个下层的东西能够处理包括线程在内的并发系统)。当 Flask 开始其内部请求处理时会把当前线程作为活动环境,并把当前应用和 WSGI 环境绑定到 这个环境(线程)。它以一种聪明的方式使得一个应用可以在不中断的情况下调用另一个 应用。

这个在做单元测试时有用。在测试 时会遇到由于没有请求对象而导致依赖于请求的代码会突然崩溃的情况。对策是自己创建 一个请求对象并绑定到环境。最简单的单元测试解决方案是使用 test_request_context() 环境管理器。通过使用 with 语句 可以绑定一个测试请求,以便于交互。例如:

from flask import request
with app.test_request_context('/hello', method='POST'):
 # now you can do something with the request until the
 # end of the with block, such as basic assertions:
 assert request.path == '/hello'
 assert request.method == 'POST'

另一种方式是把整个 WSGI 环境传递给 request_context() 方法:

from flask import request
with app.request_context(environ):
 assert request.method == 'POST'

十、请求对象

请求对象在 API 一节中有详细说明这里不细谈(参见 Request )。 这里简略地谈一下最常见的操作。首先,你必须从 flask 模块导入请求对象:

from flask import request

通过使用 method 属性可以操作当前请求方法,通过使用 form 属性处理表单数据(在 POST 或者 PUT 请求 中传输的数据)。以下是使用上述两个属性的例子:

@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)

当 form 属性中不存在这个键时会发生什么?会引发一个 KeyError 。 如果你不像捕捉一个标准错误一样捕捉 KeyError ,那么会显示一个 HTTP 400 Bad Request 错误页面。因此,多数情况下你不必处理这个问题。

要操作 URL (如 ?key=value )中提交的参数可以使用 args 属性:

searchword = request.args.get('key', '')

用户可能会改变 URL 导致出现一个 400 请求出错页面,这样降低了用户友好度。因此, 我们推荐使用 get 或通过捕捉 KeyError 来访问 URL 参数。

完整的请求对象方法和属性参见 Request 文档。

最近发表
标签列表