Skip to content

Commit 66e7d2f

Browse files
committed
Update chapter 11
1 parent 746b82d commit 66e7d2f

8 files changed

Lines changed: 46 additions & 43 deletions

File tree

chapters/11-deployment.md

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,28 @@ Web 程序通常有两种部署方式:传统部署和云部署。传统部署
1010
首先,我们需要生成一个依赖列表,方便在部署环境里安装。使用下面的命令把当前依赖列表写到一个 requirements.txt 文件里:
1111

1212
```bash
13-
(env) $ pip freeze > requirements.txt
13+
(.venv) $ pip freeze > requirements.txt
1414
```
1515

16-
对于某些配置,生产环境下需要使用不同的值。为了让配置更加灵活,我们把需要在生产环境下使用的配置改为优先从环境变量中读取,如果没有读取到,则使用默认值
16+
对于某些配置,生产环境下需要使用不同的值。这是我们之前为生产环境创建的配置类
1717

1818
```python
19-
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev')
20-
app.config['SQLALCHEMY_DATABASE_URI'] = prefix + os.path.join(os.path.dirname(app.root_path), os.getenv('DATABASE_FILE', 'data.db'))
19+
class ProductionConfig(BaseConfig):
20+
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL', SQLITE_PREFIX + str(BASE_DIR / 'data.db'))
2121
```
2222

23-
以第一个配置变量为例,`os.getenv('SECRET_KEY', 'dev')` 表示读取系统环境变量 `SECRET_KEY` 的值,如果没有获取到,则使用 `dev`
23+
在示例程序里,因为我们部署后将继续使用 SQLite,所以只需要为生产环境设置不同的数据库文件名。另外,继承自 BaseConfig 的配置 SECRET_KEY 需要改为使用随机字符:
2424

25-
> **注意** 像密钥这种敏感信息,保存到环境变量中要比直接写在代码中更加安全。
25+
```python
26+
class BaseConfig:
27+
SECRET_KEY = os.getenv('SECRET_KEY', 'dev')
28+
```
2629

27-
对于第二个配置变量,我们仅改动了最后的数据库文件名。在示例程序里,因为我们部署后将继续使用 SQLite,所以只需要为生产环境设置不同的数据库文件名,否则的话,你可以像密钥一样设置优先从环境变量读取整个数据库 URL
30+
在生产环境,为了安全考虑,需要把具体的值作为环境变量定义,而不是放到代码里。我们将在远程服务器环境创建新的 .env 文件写入 SECRET_KEY 的值,具体将在下一节介绍
2831

29-
在部署程序时,我们不会使用 Flask 内置的开发服务器运行程序,因此,对于写到 .env 文件的环境变量,我们需要手动使用 python-dotenv 导入。下面在项目根目录创建一个 wsgi.py 脚本,在这个脚本中加载环境变量,并导入程序实例以供部署时使用
32+
在部署程序时,我们不会使用 Flask 内置的开发服务器运行程序,因此,对于写到 .env 文件的环境变量,我们需要手动使用 python-dotenv 导入。下面在项目根目录创建一个 wsgi.py 脚本,作为生产环境的程序入口脚本。我们在这个脚本中加载环境变量,并创建程序实例以供部署时使用
3033

31-
*wsgi.py:手动设置环境变量并导入程序实例*
34+
*wsgi.py:手动设置环境变量并创建程序实例*
3235

3336
```python
3437
import os
@@ -39,10 +42,10 @@ dotenv_path = os.path.join(os.path.dirname(__file__), '.env')
3942
if os.path.exists(dotenv_path):
4043
load_dotenv(dotenv_path)
4144

42-
from watchlist import app
43-
```
45+
from watchlist import create_app
4446

45-
这两个环境变量的具体定义,我们将在远程服务器环境创建新的 .env 文件写入。
47+
app = create_app(config_name='production')
48+
```
4649

4750
最后让我们把改动提交到 Git 仓库,并推送到 GitHub 上的远程仓库:
4851

@@ -52,14 +55,11 @@ $ git commit -m "Ready to deploy"
5255
$ git push
5356
```
5457

55-
> **提示** 你可以在 GitHub 上查看本书示例程序的对应 commit:[92eabc8](https://github.com/helloflask/watchlist/commit/92eabc89a669a8b3e2d2a56177a875938923fd52)
56-
57-
5858
## 使用 PythonAnywhere 部署程序
5959

6060
首先访问[注册页面](https://www.pythonanywhere.com/registration/register/beginner/)注册一个免费账户。注册时填入的用户名将作为你的程序域名的子域部分,以及分配给你的 Linux 用户名。比如,如果你的用户名为 greyli,最终为你分配的程序域名就是 <http://greyli.pythonanywhere.com/>
6161

62-
注册完成后会有一个简单的教程,你可以跳过,也可以跟着了解一下基本用法。管理面板主页如下所示
62+
注册完成后会有一个简单的教程,你可以跳过,也可以跟着了解一下基本用法。管理面板(Dashboard)主页如下所示
6363

6464
![管理面板主页](images/11-1.png)
6565

@@ -71,7 +71,7 @@ $ git push
7171
- Tasks(任务):创建计划任务
7272
- Databases(数据库):设置数据库,免费账户可以使用 MySQL
7373

74-
这些链接对应页面的某些功能也可以直接在管理面板主页打开
74+
这些链接对应页面的某些功能也可以直接在管理面板主页对应部分打开
7575

7676
我们需要先来创建一个 Web 程序,你可以点击导航栏的 Web 链接,或是主页上的“Open Web tab”按钮打开 Web 面板:
7777

@@ -85,7 +85,7 @@ $ git push
8585

8686
![选择 Web 框架](images/11-4.png)
8787

88-
接着选择你想使用的 Python 版本:
88+
接着选择你想使用的 Python 版本(最低需要 3.9 版本)
8989

9090
![选择 Python 版本](images/11-5.png)
9191

@@ -103,7 +103,7 @@ $ git push
103103
* 从 GitHub 拉取我们的程序
104104
* 在本地将代码存储为压缩文件,然后在 Files 标签页上传压缩包
105105

106-
因为我们的代码已经推送到 GitHub 上,这里将采用第一种方式。首先通过管理面板主页的“Bash”按钮或是 Consoles 面板下的“Bash”链接创建一个命令行会话:
106+
因为我们的代码已经推送到 GitHub 上,这里将采用第一种方式。首先通过管理面板主页的“Bash”按钮或是 Consoles 面板下的“Bash”链接创建一个命令行会话,后续的命令都需要在新打开的会话中执行
107107

108108
![打开新的命令行会话](images/11-7.png)
109109

@@ -116,11 +116,11 @@ $ cd watchlist # 切换进程序仓库
116116

117117
这会把程序代码克隆到 PythonAnywhere 为你分配的用户目录中,路径即 `/home/你的 PythonAnywhere 用户名/你的仓库名称`,比如 `/home/greyli/watchlist`
118118

119-
注意替换 git clone 命令后的 Git 地址,将 `greyli` 替换为你的 GitHub 用户名,将 `watchlist` 替换为你的仓库名称。
119+
注意替换 git clone 命令后的 Git 地址,将 `helloflask` 替换为你的 GitHub 用户名,将 `watchlist` 替换为你的仓库名称。
120120

121121
> **提示** 如果你在 GitHub 上的仓库类型为私有仓库,那么需要将 PythonAnywhere 服务器的 SSH 密钥添加到 GitHub 账户中,具体参考第 1 章“设置 SSH 密钥”小节。
122122
123-
下面我们在项目根目录创建 .env 文件,并写入生产环境下需要设置的两个环境变量。其中,密钥(`SECRET_KEY`的值是随机字符串,我们可以使用 uuid 模块来生成:
123+
下面我们在项目根目录创建 .env 文件,并写入生产环境下需要设置的环境变量。密钥(`SECRET_KEY`的值需要为随机字符串,我们可以使用 uuid 模块来生成。在你本地的终端中打开 Python Shell 并执行相应代码
124124

125125
```python
126126
$ python3
@@ -129,30 +129,33 @@ $ python3
129129
'3d6f45a5fc12445dbac2f59c3b6c7cb1'
130130
```
131131

132-
复制生成的随机字符备用,接着创建 .env 文件:
132+
复制生成的随机字符备用,接着回到 PythonAnywhere 上打开的命令行会话,执行下面的命令创建 .env 文件:
133133

134134
```bash
135135
$ nano .env
136136
```
137137

138-
写入设置密钥和数据库名称的环境变量
138+
写入设置密钥的环境变量(按下 Control+O 和 Enter 保存,然后按下 Control+X 退出)
139139

140140
```ini
141141
SECRET_KEY=3d6f45a5fc12445dbac2f59c3b6c7cb1
142-
DATABASE_FILE=data-prod.db
143142
```
144143

145144
最后安装依赖并执行初始化操作:
146145

147146
```bash
148-
$ python3 -m venv env # 创建虚拟环境
149-
$ . env/bin/activate # 激活虚拟环境
150-
(env) $ pip install -r requirements.txt # 安装所有依赖
151-
(env) $ flask init-db # 初始化数据库
152-
(env) $ flask admin # 创建管理员账户
147+
$ python3 -m venv .venv # 创建虚拟环境
148+
$ source .venv/bin/activate # 激活虚拟环境
149+
(.venv) $ pip install -r requirements.txt # 安装所有依赖
150+
(.venv) $ flask init-db # 初始化数据库,也可以执行 flask forge 创建虚拟数据
151+
(.venv) $ flask admin # 创建管理员账户
153152
```
154153

155-
先不要关闭这个标签页,后面我们还要在这里执行一些命令。点击右上角的菜单按钮,并在浏览器的新标签页打开 Web 面板。
154+
你的命令行窗口和依次输入的命令(省略了后两条命令)类似下图:
155+
156+
![代码配置](images/11-8.png)
157+
158+
先不要关闭这个标签页,后面我们还要在这里执行一些命令。点击右上角的菜单按钮,并在浏览器的后台标签页打开 Web 面板。
156159

157160

158161
## 设置并启动程序
@@ -162,9 +165,9 @@ $ . env/bin/activate # 激活虚拟环境
162165

163166
### 代码
164167

165-
回到 Web 标签页,先来设置 Code 部分的配置:
168+
切换到 Web 面板(标签页,先来设置 Code 部分的配置:
166169

167-
![代码配置](images/11-8.png)
170+
![代码配置](images/11-9.png)
168171

169172
点击源码(Source code)和工作目录(Working directory)后的路径并填入项目根目录,目录规则为“/home/用户名/项目文件夹名”。
170173

@@ -189,36 +192,36 @@ PythonAnywhere 会自动从这个文件里导入名称为 `application` 的程
189192

190193
为了让程序正确运行,我们需要在 Virtualenv 部分填入虚拟环境文件夹的路径:
191194

192-
![虚拟环境配置](images/11-9.png)
195+
![虚拟环境配置](images/11-10.png)
193196

194-
对应我们的项目就是 `/home/greyli/watchlist/env/`,注意替换其中的用户名、项目名称和虚拟环境名称部分。点击 Virtualenv 部分的红色字体链接,填入并保存。
197+
对应我们的项目就是 `/home/greyli/watchlist/.venv/`,注意替换其中的用户名、项目名称和虚拟环境名称部分。点击 Virtualenv 部分的红色字体链接,填入并保存。
195198

196199

197200
### 静态文件
198201

199-
静态文件可以交给 PythonAnywhere 设置的服务器来处理,这样会更高效。要让 PythonAnywhere 处理静态文件,我们只需要在 Static files 部分指定静态文件 URL 和对应的静态文件文件夹目录,如下所示:
202+
静态文件可以交给 PythonAnywhere 设置的 Web 服务器来处理,这样处理性能会更好。要让 PythonAnywhere 处理静态文件,我们只需要在 Static files 部分指定静态文件 URL 和对应的静态文件文件夹目录,如下所示:
200203

201-
![静态文件配置](images/11-10.png)
204+
![静态文件配置](images/11-11.png)
202205

203-
注意更新目录中的用户名和项目文件夹名称。
206+
Flask 程序的静态文件默认 URL 为“/static”,因此这里的 URL 填入“/static/”;对应的目录是程序包里的静态文件夹,比如“/home/greyli/watchlist/watchlist/static/”。注意更新目录中的用户名和项目文件夹名称。
204207

205208

206209
### 启动程序
207210

208-
一切就绪,点击绿色的重载按钮即可让配置生效
211+
一切就绪,点击绿色的重载(Reload)按钮即可让配置生效
209212

210-
![重载程序](images/11-11.png)
213+
![重载程序](images/11-12.png)
211214

212-
现在访问你的程序网址“<https://用户名.pythonanywhere.com>”(Web 面板顶部的链接),比如 <https://greyli.pythonanywhere.com> 即可访问程序。
215+
现在访问你的程序网址“<https://用户名.pythonanywhere.com>”(可以在 Web 面板顶部找到链接),比如 <https://greyli.pythonanywhere.com> 即可访问程序。
213216

214217
最后还要注意的是,免费账户需要每三个月点击一次黄色的激活按钮(在过期前你会收到提醒邮件):
215218

216-
![激活程序](images/11-12.png)
219+
![激活程序](images/11-13.png)
217220

218221

219222
## 更新部署后的程序
220223

221-
当你需要更新程序时,流程和部署类似。在本地完成更新,确保程序通过测试后,将代码推送到 GitHub 上的远程仓库。登录到 PythonAnywhere,打开一个命令行会话(Bash),切换到项目目录,使用 git pull 命令从远程仓库拉取更新:
224+
当你需要更新程序时,流程和部署类似。在本地完成更新,确保程序通过测试后,将代码推送到 GitHub 上的远程仓库。然后登录到 PythonAnywhere,打开一个命令行会话(Bash),切换到项目目录,使用 git pull 命令从远程仓库拉取更新:
222225

223226
```bash
224227
$ cd watchlist
@@ -232,7 +235,7 @@ $ git pull
232235

233236
程序部署上线以后,你可以考虑继续为它开发新功能,也可以从零编写一个新的程序。虽然本书即将接近尾声,但你的学习之路才刚刚开始,因为本书只是介绍了 Flask 入门所需的基础知识,你还需要进一步学习。在后记中,你可以看到进一步学习的推荐读物。
234237

235-
接下来,有一个挑战在等着你
238+
接下来,还有一个挑战在等着你
236239

237240

238241
## 进阶提示

chapters/images/11-10.png

-9.09 KB
Loading

chapters/images/11-11.png

17.2 KB
Loading

chapters/images/11-12.png

-27.9 KB
Loading

chapters/images/11-13.png

43.5 KB
Loading

chapters/images/11-5.png

35.6 KB
Loading

chapters/images/11-8.png

180 KB
Loading

chapters/images/11-9.png

27.5 KB
Loading

0 commit comments

Comments
 (0)