Flask Web开发

来源:互联网 发布:java 八皇后算法 编辑:程序博客网 时间:2024/05/19 19:16

示例地址 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 会将其渲染成 '&lt;h1&gt;Hello&lt;/
h1&gt;',浏览器能显示这个 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 对象中。这个对象还提供了一些方法,可以从文件或环境中导入配置值。

为了增强安全性,密钥不应该直接写入代码,而要保存在环境变量中。

0 0
原创粉丝点击