Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e30ef31

Browse files
add flask web.
1 parent 5552d59 commit e30ef31

File tree

99 files changed

+9594
-4137
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+9594
-4137
lines changed

‎04_flask/01_Flask介绍.md‎

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# 第 1 章:Hello, Flask!
2+
3+
追溯到最初,Flask 诞生于 Armin Ronacher 在 2010 年愚人节开的一个玩笑。后来,它逐渐发展成为一个成熟的 Python Web 框架,越来越受到开发者的喜爱。目前它在 GitHub 上是 Star 数量最多的 Python Web 框架,没有之一。
4+
5+
Flask 是典型的微框架,作为 Web 框架来说,它仅保留了核心功能:**请求响应处理****模板渲染**。这两类功能分别由 Werkzeug(WSGI 工具库)完成和 Jinja(模板渲染库)完成,因为 Flask 包装了这两个依赖,我们暂时不用深入了解它们。
6+
7+
## 主页
8+
9+
这一章的主要任务就是为我们的程序编写一个简单的主页。主页的 URL 一般就是根地址,即 `/`。当用户访问根地址的时候,我们需要返回一行欢迎文字。这个任务只需要下面几行代码就可以完成:
10+
11+
*app.py:程序主页*
12+
13+
```python
14+
from flask import Flask
15+
app = Flask(__name__)
16+
17+
@app.route('/')
18+
def hello():
19+
return 'Welcome to My Watchlist!'
20+
```
21+
22+
按照惯例,我们把程序保存为 app.py,确保当前目录是项目的根目录,并且激活了虚拟环境,然后在命令行窗口执行 `flask run` 命令启动程序(按下 Control + C 可以退出):
23+
24+
```bash
25+
(env) $ flask run
26+
* Serving Flask app "app.py"
27+
* Environment: production
28+
WARNING: Do not use the development server in a production environment.
29+
Use a production WSGI server instead.
30+
* Debug mode: off
31+
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
32+
```
33+
34+
现在打开浏览器,访问 <http://localhost:5000> 即可访问我们的程序主页,并看到我们在程序里返回的问候语,如下图所示:
35+
36+
![主页](../docs/flask_images/2-1.png)
37+
38+
执行 `flask run` 命令时,Flask 会使用内置的开发服务器来运行程序。这个服务器默认监听本地机的 5000 端口,也就是说,我们可以通过在地址栏输入 <http://127.0.0.1:5000> 或是 <http://localhost:5000> 访问程序。
39+
40+
> **注意** 内置的开发服务器只能用于开发时使用,部署上线的时候要换用性能更好的服务器,我们会在最后一章学习。
41+
42+
## 代码解析
43+
44+
下面我们来分解这个 Flask 程序,了解它的基本构成。
45+
46+
首先我们从 `flask` 包导入 `Flask` 类,通过实例化这个类,创建一个程序对象 `app`:
47+
48+
```python
49+
from flask import Flask
50+
app = Flask(__name__)
51+
```
52+
53+
接下来,我们要注册一个处理函数,这个函数是处理某个请求的处理函数,Flask 官方把它叫做视图函数(view funciton),你可以理解为"**请求处理函数**"。
54+
55+
所谓的"注册",就是给这个函数戴上一个装饰器帽子。我们使用 `app.route()` 装饰器来为这个函数绑定对应的 URL,当用户在浏览器访问这个 URL 的时候,就会触发这个函数,获取返回值,并把返回值显示到浏览器窗口:
56+
57+
```python
58+
@app.route('/')
59+
def hello():
60+
return 'Welcome to My Watchlist!'
61+
```
62+
63+
> **提示** 为了便于理解,你可以把 Web 程序看作是一堆这样的视图函数的集合:编写不同的函数处理对应 URL 的请求。
64+
65+
填入 `app.route()` 装饰器的第一个参数是 URL 规则字符串,这里的 `/`指的是根地址。
66+
67+
我们只需要写出相对地址,主机地址、端口号等都不需要写出。所以说,这里的 `/` 对应的是主机名后面的路径部分,完整 URL 就是 <http://localhost:5000/>。如果我们这里定义的 URL 规则是 `/hello`,那么完整 URL 就是 <http://localhost:5000/hello>
68+
69+
整个请求的处理过程如下所示:
70+
71+
1. 当用户在浏览器地址栏访问这个地址,在这里即 <http://localhost:5000/>
72+
2. 服务器解析请求,发现请求 URL 匹配的 URL 规则是 `/`,因此调用对应的处理函数 `hello()`
73+
3. 获取 `hello()` 函数的返回值,处理后返回给客户端(浏览器)
74+
4. 浏览器接受响应,将其显示在窗口上
75+
76+
77+
## 实验时间
78+
79+
在这个小节,我们可以通过做一些实验,来扩展和加深对本节内容的理解。
80+
81+
### 修改视图函数返回值
82+
83+
首先,你可以自由修改视图函数的返回值,比如:
84+
85+
```python
86+
@app.route('/')
87+
def hello():
88+
return u'欢迎来到我的 Watchlist!'
89+
```
90+
91+
返回值作为响应的主体,默认会被浏览器作为 HTML 格式解析,所以我们可以添加一个 HTML 元素标记:
92+
93+
```python
94+
@app.route('/')
95+
def hello():
96+
return '<h1>Hello Totoro!</h1><img src="http://helloflask.com/totoro.gif">'
97+
```
98+
99+
保存修改后,只需要在浏览器里刷新页面,你就会看到页面上的内容也会随之变化。
100+
101+
![2-2](../docs/flask_images/2-2.png)
102+
103+
### 修改 URL 规则
104+
105+
另外,你也可以自由修改传入 `app.route` 装饰器里的 URL 规则字符串,但要注意以斜线 `/` 作为开头。比如:
106+
107+
```python
108+
@app.route('/home')
109+
def hello():
110+
return 'Welcome to My Watchlist!'
111+
```
112+
113+
保存修改,这时刷新浏览器,则会看到一个 404 错误提示,提示页面未找到(Page Not Found)。这是因为视图函数的 URL 改成了 `/home`,而我们刷新后访问的地址仍然是旧的 `/`。如果我们把访问地址改成 <http://localhost:5000/home>,就会正确看到返回值。
114+
115+
一个视图函数也可以绑定多个 URL,这通过附加多个装饰器实现,比如:
116+
117+
```python
118+
@app.route('/')
119+
@app.route('/index')
120+
@app.route('/home')
121+
def hello():
122+
return 'Welcome to My Watchlist!'
123+
```
124+
125+
现在无论是访问 <http://localhost:5000/><http://localhost:5000/home> 还是 <http://localhost:5000/index> 都可以看到返回值。
126+
127+
在前面,我们之所以把传入 `app.route` 装饰器的参数称为 URL 规则,是因为我们也可以在 URL 里定义变量部分。比如下面这个视图函数会处理所有类似 `/user/<name>` 的请求:
128+
129+
```python
130+
@app.route('/user/<name>')
131+
def user_page(name):
132+
return 'User page'
133+
```
134+
135+
不论你访问 <http://localhost:5000/user/greyli>,还是 <http://localhost:5000/user/peter>,抑或是 <http://localhost:5000/user/甲>,都会触发这个函数。通过下面的方式,我们也可以在视图函数里获取到这个变量值:
136+
137+
```python
138+
from flask import escape
139+
140+
@app.route('/user/<name>')
141+
def user_page(name):
142+
return 'User: %s' % escape(name)
143+
```
144+
145+
> **注意** 用户输入的数据会包含恶意代码,所以不能直接作为响应返回,需要使用 Flask 提供的 escape() 函数对 name 变量进行转义处理,比如把 `<` 转换成 `&lt;`。这样在返回响应时浏览器就不会把它们当做代码执行。
146+
147+
### 修改视图函数名?
148+
149+
最后一个可以修改的部分就是视图函数的名称了。首先,视图函数的名字是自由定义的,和 URL 规则无关。和定义其他函数或变量一样,只需要让它表达出所要处理页面的含义即可。
150+
151+
除此之外,它还有一个重要的作用:作为代表某个路由的端点(endpoint),同时用来生成 URL。对于程序内的 URL,为了避免手写,Flask 提供了一个 `url_for` 函数来生成 URL,它接受的第一个参数就是端点值,默认为视图函数的名称:
152+
153+
```python
154+
from flask import url_for, escape
155+
156+
# ...
157+
158+
@app.route('/')
159+
def hello():
160+
return 'Hello'
161+
162+
@app.route('/user/<name>')
163+
def user_page(name):
164+
return 'User: %s' % escape(name)
165+
166+
@app.route('/test')
167+
def test_url_for():
168+
# 下面是一些调用示例(请在命令行窗口查看输出的 URL):
169+
print(url_for('hello')) # 输出:/
170+
# 注意下面两个调用是如何生成包含 URL 变量的 URL 的
171+
print(url_for('user_page', name='greyli')) # 输出:/user/greyli
172+
print(url_for('user_page', name='peter')) # 输出:/user/peter
173+
print(url_for('test_url_for')) # 输出:/test
174+
# 下面这个调用传入了多余的关键字参数,它们会被作为查询字符串附加到 URL 后面。
175+
print(url_for('test_url_for', num=2)) # 输出:/test?num=2
176+
return 'Test page'
177+
```
178+
179+
实验过程中编写的代码可以删掉,也可以保留,但记得为根地址返回一行问候,这可是我们这一章的任务。

‎04_flask/02_Flask模板.md‎

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# 第 2 章:模板
2+
3+
在一般的 Web 程序里,访问一个地址通常会返回一个包含各类信息的 HTML 页面。因为我们的程序是动态的,页面中的某些信息需要根据不同的情况来进行调整,比如对登录和未登录用户显示不同的信息,所以页面需要在用户访问时根据程序逻辑动态生成。
4+
5+
我们把包含变量和运算逻辑的 HTML 或其他格式的文本叫做**模板**,执行这些变量替换和逻辑计算工作的过程被称为**渲染**,这个工作由我们这一章要学习使用的模板渲染引擎——Jinja2 来完成。
6+
7+
按照默认的设置,Flask 会从程序实例所在模块同级目录的 templates 文件夹中寻找模板,我们的程序目前存储在项目根目录的 app.py 文件里,所以我们要在项目根目录创建这个文件夹:
8+
9+
```bash
10+
$ mkdir templates
11+
```
12+
13+
## 模板基本语法
14+
15+
在社交网站上,每个人都有一个主页,借助 Jinja2 就可以写出一个通用的模板。
16+
17+
Jinja2 的语法和 Python 大致相同,你在后面会陆续接触到一些常见的用法。在模板里,你需要添加特定的定界符将 Jinja2 语句和变量标记出来,下面是三种常用的定界符:
18+
19+
- `{{ ... }}` 用来标记变量。
20+
- `{% ... %}` 用来标记语句,比如 if 语句,for 语句等。
21+
- `{# ... #}` 用来写注释。
22+
23+
模板中使用的变量需要在渲染的时候传递进去,具体我们后面会了解。
24+
25+
## 编写主页模板
26+
27+
我们先在 templates 目录下创建一个 index.html 文件,作为主页模板。主页需要显示电影条目列表和个人信息,代码如下所示:
28+
29+
*templates/index.html:主页模板*
30+
31+
```jinja2
32+
<!DOCTYPE html>
33+
<html lang="en">
34+
<head>
35+
<meta charset="utf-8">
36+
<title>{{ name }}'s Watchlist</title>
37+
</head>
38+
<body>
39+
<h2>{{ name }}'s Watchlist</h2>
40+
{# 使用 length 过滤器获取 movies 变量的长度 #}
41+
<p>{{ movies|length }} Titles</p>
42+
<ul>
43+
{% for movie in movies %} {# 迭代 movies 变量 #}
44+
<li>{{ movie.title }} - {{ movie.year }}</li> {# 等同于 movie['title'] #}
45+
{% endfor %} {# 使用 endfor 标签结束 for 语句 #}
46+
</ul>
47+
<footer>
48+
<small>&copy; 2018 <a href="http://helloflask.com/tutorial">HelloFlask</a></small>
49+
</footer>
50+
</body>
51+
</html>
52+
```
53+
54+
为了方便对变量进行处理,Jinja2 提供了一些过滤器,语法形式如下:
55+
56+
```jinja2
57+
{{ 变量|过滤器 }}
58+
```
59+
60+
左侧是变量,右侧是过滤器名。比如,上面的模板里使用 `length` 过滤器来获取 `movies` 的长度,类似 Python 里的 `len()` 函数。
61+
62+
> **提示** 访问 <http://jinja.pocoo.org/docs/2.10/templates/#list-of-builtin-filters> 查看所有可用的过滤器。
63+
64+
## 准备虚拟数据
65+
66+
为了模拟页面渲染,我们需要先创建一些虚拟数据,用来填充页面内容:
67+
68+
*app.py:定义虚拟数据*
69+
70+
```python
71+
name = 'Grey Li'
72+
movies = [
73+
{'title': 'My Neighbor Totoro', 'year': '1988'},
74+
{'title': 'Dead Poets Society', 'year': '1989'},
75+
{'title': 'A Perfect World', 'year': '1993'},
76+
{'title': 'Leon', 'year': '1994'},
77+
{'title': 'Mahjong', 'year': '1996'},
78+
{'title': 'Swallowtail Butterfly', 'year': '1996'},
79+
{'title': 'King of Comedy', 'year': '1999'},
80+
{'title': 'Devils on the Doorstep', 'year': '1999'},
81+
{'title': 'WALL-E', 'year': '2008'},
82+
{'title': 'The Pork of Music', 'year': '2012'},
83+
]
84+
```
85+
86+
## 渲染主页模板
87+
88+
使用 `render_template()` 函数可以把模板渲染出来,必须传入的参数为模板文件名(相对于 templates 根目录的文件路径),这里即 `'index.html'`。为了让模板正确渲染,我们还要把模板内部使用的变量通过关键字参数传入这个函数,如下所示:
89+
90+
*app.py:返回渲染好的模板作为响应*
91+
92+
```python
93+
from flask import Flask, render_template
94+
95+
# ...
96+
97+
@app.route('/')
98+
def index():
99+
return render_template('index.html', name=name, movies=movies)
100+
```
101+
102+
为了更好的表示这个视图函数的作用,我们把原来的函数名 `hello` 改为 `index`,意思是"索引",即主页。
103+
104+
在传入 `render_template()` 函数的关键字参数中,左边的 `movies` 是模板中使用的变量名称,右边的 `movies` 则是该变量指向的实际对象。这里传入模板的 `name` 是字符串,`movies` 是列表,但能够在模板里使用的不只这两种 Python 数据结构,你也可以传入元组、字典、函数等。
105+
106+
`render_template()` 函数在调用时会识别并执行 index.html 里所有的 Jinja2 语句,返回渲染好的模板内容。在返回的页面中,变量会被替换为实际的值(包括定界符),语句(及定界符)则会在执行后被移除(注释也会一并移除)。
107+
108+
现在访问 <http://localhost:5000/> 看到的程序主页如下图所示:
109+
110+
![主页电影列表](../docs/flask_images/3-1.png)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /