您的位置:首页 > 其它

Flask Web开发

2015-11-15 11:51 211 查看
示例地址 https://github.com/miguelgrinberg/flasky
第一章 安装

1.1使用虚拟环境

virtualenv --version查看安装VENV的版本

Python 3.3 通过 venv 模块原生支持虚拟环境,命令为 pyvenv。pyvenv 可以替

代 virtualenv。不过要注意,在 Python 3.3 中使用 pyvenv 命令创建的虚拟环

境不包含 pip,你需要进行手动安装。Python 3.4 改进了这一缺陷,pyvenv 完

全可以代替 virtualenv。

按照惯例,一般虚拟环境会被命名为 venv

激活命令是: venv\Scripts\activate

虚拟环境被激活后,其中 Python 解释器的路径就被添加进 PATH 中,但这种改变不是永久性的,它只会影响当前的命令行会话。

第二章 程序的基本结构

@app.route('/user/<name>')

尖括号中的内容就是动态部分,任何能匹配静态部分的 URL 都会映射到这个路由上。调用视图函数时,Flask 会将动态部分作为参数传入函数。

路由中的动态部分默认使用字符串,不过也可使用类型定义。例如,路由 /user/<int:id>只会匹配动态片段 id 为整数的 URL。Flask 支持在路由中使用 int、float 和 path 类型。path 类型也是字符串,但不把斜线视作分隔符,而将其当作动态片段的一部分。

2.5.1 程序和请求上下文

为了避免大量可有可无的参数把视图函数弄得一团糟,Flask 使用上下文临时把某些对象变为全局可访问。

在 Flask 中有两种上下文:程序上下文和请求上下文。

current_app 程序上下文 当前激活程序的程序实例

g 程序上下文 处理请求时用作临时存储的对象。每次请求都会重设这个变量

request 请求上下文 请求对象,封装了客户端发出的 HTTP 请求中的内容

session 请求上下文 用户会话,用于存储请求之间需要“记住”的值的词典

Flask 在分发请求之前激活(或推送)程序和请求上下文,请求处理完成后再将其删除。程

序上下文被推送后,就可以在线程中使用 current_app 和 g 变量。类似地,请求上下文被

推送后,就可以使用 request 和 session 变量。如果使用这些变量时我们没有激活程序上

下文或请求上下文,就会导致错误。

>>> app_ctx = app.app_context()

>>> app_ctx.push()

>>> current_app.name

'hello'

>>> app_ctx.pop()

在这个例子中,没激活程序上下文之前就调用 current_app.name 会导致错误,但推送完上

下文之后就可以调用了。注意,在程序实例上调用 app.app_context() 可获得一个程序上

下文。

URL 映射是 URL 和视图函数之间的对应关系。Flask 使用 app.route 修饰器或者非修饰器形式的 app.add_url_rule() 生成映射。

app.url_map检查生成的映射

/static/<filename> 路由是Flask 添加的特殊路由,用于访问静态文件。

URL 映射中的 HEAD、Options、GET 是请求方法,由路由进行处理。

为了避免在每个视图函数中都使用重复的代码,Flask 提供了注册通用函数的功能,注册的函数可在请求被分发到视图函数之前或之后调用。

请求钩子使用修饰器实现。

Flask 支持以下 4 种钩子

• before_first_request:注册一个函数,在处理第一个请求之前运行。

• before_request:注册一个函数,在每次请求之前运行。

• after_request:注册一个函数,如果没有未处理的异常抛出,在每次请求之后运行。

• teardown_request:注册一个函数,即使有未处理的异常抛出,也在每次请求之后运行。

在请求钩子函数和视图函数之间共享数据一般使用上下文全局变量 g。例如,before_request 处理程序可以从数据库中加载已登录用户,并将其保存到 g.user 中。随后调用视

图函数时,视图函数再使用 g.user 获取用户。

如果视图函数返回的响应需要使用不同的状态码,那么可以把数字代码作为第二个返回

值,添加到响应文本之后。例如,下述视图函数返回一个 400 状态码,表示请求无效:

@app.route('/')

def index():

return '<h1>Bad Request</h1>', 400

视图函数返回的响应还可接受第三个参数,这是一个由首部(header)组成的字典,可以

添加到 HTTP 响应中。一般情况下并不需要这么做,不过你会在第 14 章看到一个例子。

如果不想返回由 1 个、2 个或 3 个值组成的元组,Flask 视图函数还可以返回 Response 对

象。make_response() 函数可接受 1 个、2 个或 3 个参数(和视图函数的返回值一样),并

返回一个 Response 对象。有时我们需要在视图函数中进行这种转换,然后在响应对象上调

用各种方法,进一步设置响应。下例创建了一个响应对象,然后设置了 cookie:

from flask import make_response

@app.route('/')

def index():

response = make_response('<h1>This document carries a cookie!</h1>')

response.set_cookie('answer', '42')

return response

有一种名为重定向的特殊响应类型。

<pre name="code" class="python">from flask import redirect

@app.route('/')
def index():
return redirect('http://www.example.com')



还有一种特殊的响应由 abort 函数生成,用于处理错误。

注意,abort 不会把控制权交还给调用它的函数,而是抛出异常把控制权交给 Web 服务器。

专为 Flask 开发的扩展都暴漏在 flask.ext 命名空间下。

第三章 模板

视图函数的作用很明确,即生成请求的响应。

业务逻辑和表现逻辑

默认情况下,Flask 在程序文件夹中的 templates 子文件夹中寻找模板

@app.route('/user/<name>')
def user(name):
return render_template('user.html', name=name)
Flask 提供的 render_template 函数把 Jinja2 模板引擎集成到了程序中。render_template 函数的第一个参数是模板的文件名。随后的参数都是键值对,表示模板中变量对应的真实值。

模板中使用的 {{ name }} 结构表示一个变量,它是一种特殊的占位符,告诉模

板引擎这个位置的值从渲染模板时使用的数据中获取。

Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。在模板中使用变量的一些示例如下:

<p>A value from a dictionary: {{ mydict['key'] }}.</p>

<p>A value from a list: {{ mylist[3] }}.</p>

<p>A value from a list, with a variable index: {{ mylist[myintvar] }}.</p>

<p>A value from an object's method: {{ myobj.somemethod() }}.</p>

可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。

safe 过滤器值得特别说明一下。默认情况下,出于安全考虑,Jinja2 会转义所有变量。例如,如果一个变量的值为 '<h1>Hello</h1>',Jinja2 会将其渲染成 '<h1>Hello</

h1>',浏览器能显示这个 h1 元素,但不会进行解释。

{% if user %}
Hello, {{ user }}!
{% else %}
Hello, Stranger!
{% endif %}


<ul>
{% for comment in comments %}
<li>{{ comment }}</li>
{% endfor %}
</ul>


Jinja2 还支持宏。宏类似于 Python 代码中的函数。例如:

{% macro render_comment(comment) %}
<li>{{ comment }}</li>
{% endmacro %}
<ul>
{% for comment in comments %}
{{ render_comment(comment) }}
{% endfor %}
</ul>

为了重复使用宏,我们可以将其保存在单独的文件中,然后在需要使用的模板中导入:

{% import 'macros.html' as macros %}
<ul>
{% for comment in comments %}
{{ macros.render_comment(comment) }}
{% endfor %}
</ul>


需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免重复:

{% include 'common.html' %}

另一种重复使用代码的强大方式是模板继承,它类似于 Python 代码中的类继承。首先,创建一个名为 base.html 的基模板:

<html>
<head>
{% block head %}
<title>{% block title %}{% endblock %} - My Application</title>
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>


block 标签定义的元素可在衍生模板中修改。在本例中,我们定义了名为 head、title 和body 的块。注意,title 包含在 head 中。下面这个示例是基模板的衍生模板:

{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style>
</style>
{% endblock %}
{% block body %}
<h1>Hello, World!</h1>
{% endblock %}


extends 指令声明这个模板衍生自 base.html。在 extends 指令之后,基模板中的 3 个块被重新定义,模板引擎会将其插入适当的位置。注意新定义的 head 块,在基模板中其内容不是空的,所以使用 super() 获取原来的内容。

Flask 提供了 url_for() 辅助函数,它可以使用程序 URL 映射中保存的信息生成 URL。

调用 url_for('index', _external=True) 返回的则是绝对地址,在这个示例中是 http://localhost:5000/。
使用 url_for() 生成动态地址时,将动态部分作为关键字参数传入。例如,url_for('user', name='john', _external=True) 的返回结果是 http://localhost:5000/user/john。
传入 url_for() 的关键字参数不仅限于动态路由中的参数。函数能将任何额外参数添加到查询字符串中。例如,url_for('index', page=2) 的返回结果是 /?page=2。

默认设置下,Flask 在程序根目录中名为 static 的子目录中寻找静态文件。

{% block head %}
{{ super() }}
<link rel="shortcut icon" href="{{ url_for('static', filename = 'favicon.ico') }}"
type="image/x-icon">
<link rel="icon" href="{{ url_for('static', filename = 'favicon.ico') }}"
type="image/x-icon">
{% endblock %}


第四章 WEB表单

默认情况下,Flask-WTF 能保护所有表单免受跨站请求伪造(Cross-Site Request Forgery,CSRF)的攻击。恶意网站把请求发送到被攻击者已登录的其他网站时就会引发 CSRF 攻击。

app.config 字典可用来存储框架、扩展和程序本身的配置变量。使用标准的字典句法就能把配置值添加到 app.config 对象中。这个对象还提供了一些方法,可以从文件或环境中导入配置值。

为了增强安全性,密钥不应该直接写入代码,而要保存在环境变量中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: