部署学习日志

现在,我们有了一个看起来很专业的项目,让我们把它部署到实时服务器上,这样任何有网络连接的人都可以使用它。我们将使用 Platform.sh,这是一个基于网络的平台,允许你管理网络应用程序的部署。我们将在 Platform.sh 上运行学习日志。

创建 Platform.sh 帐户

要注册账户,请访问 https://platform.sh 并单击 "免费试用" 按钮。目前,Platform.sh 有一个免费层,不需要信用卡。在试用期内,您可以使用最少的资源部署应用程序,这样您就可以在使用付费托管计划之前在实时部署中测试您的项目。

随着托管平台打击垃圾邮件和滥用资源,试用计划的具体限制往往会定期更改。您可以登录 https://platform.sh/free-trial 查看免费试用的当前限制。

安装 Platform.sh CLI

要在 Platform.sh 上部署和管理项目,您需要命令行界面 (CLI) 中提供的工具。要安装最新版本的 CLI,请访问 https://docs.platform.sh/development/cli.xhtml ,并按照操作系统的说明进行操作。

在大多数系统中,您可以通过在终端运行以下命令来安装 CLI:

$ curl -fsS https://platform.sh/cli/installer | php

运行该命令后,您需要打开一个新的终端窗口,然后才能使用 CLI。

该命令可能无法在 Windows 的标准终端中运行。您可以使用 Windows Subsystem for Linux (WSL) 或 Git Bash 终端。如果需要安装 PHP,可以使用 https://apachefriends.org 中的 XAMPP 安装程序。如果在安装 Platform.sh CLI 时遇到困难,请参阅附录 E 中更详细的安装说明。

安装 platformshconfig

你还需要安装一个额外的软件包,即 platformshconfig。该软件包可帮助检测项目是在本地系统上运行,还是在 Platform.sh 服务器上运行。在活动的虚拟环境中,发出以下命令:

(ll_env)learning_log$ pip install platformshconfig

当项目在实时服务器上运行时,我们将使用该软件包修改项目设置。

创建 requirements.txt 文件

远程服务器需要知道 Learning Log 依赖于哪些软件包,因此我们将使用 pip 生成一个文件,列出这些软件包。同样,在活动的虚拟环境中,发出以下命令:

(ll_env)learning_log$ pip freeze > requirements.txt

freeze 命令会让 pip 将项目中当前安装的所有软件包名称写入 requirements.txt 文件。打开该文件可查看项目中安装的软件包和版本号:

requirements.txt
asgiref==3.5.2
beautifulsoup4==4.11.1
Django==4.1
django-bootstrap5==21.3
platformshconfig==2.4.0
soupsieve==2.3.2.post1
sqlparse==0.4.2

Learning Log 已经依赖于七个不同软件包的特定版本,因此它需要一个匹配的环境才能在远程服务器上正常运行。(我们手动安装了其中三个软件包,另外四个是作为这些软件包的依赖项自动安装的)。

当我们部署学习日志时,Platform.sh 会安装 requirements.txt 中列出的所有软件包,创建一个与我们本地使用的软件包相同的环境。正因为如此,我们可以确信部署后的项目会像在本地系统上一样正常运行。当你开始在系统上构建和维护多个项目时,这种管理项目的方法至关重要。

如果系统中列出的软件包版本号与此处显示的不同,请保留系统中的版本。

额外的部署要求

实时服务器需要两个额外的软件包。这些软件包用于在生产环境中为项目提供服务,因为在生产环境中可能会有许多用户同时提出请求。

在保存 requirements.txt 的同一目录下,新建一个名为 requirements_remote.txt 的文件。添加以下两个软件包:

requirements_remote.txt
# Requirements for live project.
gunicorn
psycopg2

gunicorn 软件包会响应远程服务器收到的请求;它取代了我们在本地使用的开发服务器。需要使用 psycopg2 软件包来让 Django 管理 Platform.sh 使用的 Postgres 数据库。Postgres 是一个开源数据库,非常适合生产应用程序。

添加配置文件

每个托管平台都需要一些配置,项目才能在其服务器上正常运行。在本节中,我们将添加三个配置文件:

.platform.app.yaml

这是项目的主要配置文件。它告诉 Platform.sh 我们要部署什么样的项目,项目需要什么样的资源,还包括在服务器上构建项目的命令。

.platform/routes.yaml

该文件定义了项目的路由。当 Platform.sh 收到请求时,该配置可帮助将这些请求导向我们的特定项目。

.platform/services.yaml

该文件定义了项目所需的其他服务。

这些都是 YAML(YAML 不是标记语言)文件。YAML 是一种专为编写配置文件而设计的语言,人类和计算机都能轻松读取。您可以手动编写或修改典型的 YAML 文件,但计算机也可以读取并明确解释该文件。

YAML 文件非常适合部署配置,因为它能让你很好地控制部署过程中发生的事情。

使隐藏文件可见

大多数操作系统都会隐藏以点开头的文件和文件夹,如 .platform。当你打开文件浏览器时,默认情况下是看不到这类文件和文件夹的。但作为程序员,你需要查看它们。以下是根据操作系统查看隐藏文件的方法:

在 Windows 系统中,打开 Windows 资源管理器,然后打开桌面等文件夹。单击 "查看 "选项卡,确保选中文件名扩展名和隐藏项。

在 macOS 上,你可以在任何 Finder 窗口中按 ⌘-SHIFT-. (点) 查看隐藏的文件和文件夹。

在 Ubuntu 等 Linux 系统上,你可以在任何文件浏览器中按下 CTRL-H 来显示隐藏的文件和文件夹。要将此设置永久化,请打开 Nautilus 等文件浏览器,然后单击选项选项卡(由三条线表示)。选择 "显示隐藏文件 "复选框。

.platform.app.yaml 配置文件

第一个配置文件最长,因为它控制着整个部署过程。我们将分段显示它;你可以在文本编辑器中手动输入,也可以从 https://ehmatthes.github.io/pcc_3e 的在线资源中下载一份。

下面是 .platform.app.yaml 的第一部分,应与 manage.py 保存在同一目录下:

.platform.app.yaml
❶ name: "ll_project"
  type: "python:3.10"

❷ relationships:
      database: "db:postgresql"

# The configuration of the app when it's exposed to the web.
❸ web:
      upstream:
          socket_family: unix
      commands:
❹         start: "gunicorn -w 4 -b unix:$SOCKET ll_project.wsgi:application"
❺     locations:
           "/":
                passthru: true
            "/static":
                root: "static"
                expires: 1h
                allow: true
# The size of the persistent disk of the application (in MB).
❻ disk: 512

保存该文件时,请确保在文件名开头加上圆点。如果省略了圆点,Platform.sh 将无法找到该文件,也就无法部署项目。

在这一点上,你不需要了解 .platform.app.yaml 中的所有内容;我将重点介绍配置中最重要的部分。该文件首先指定了项目的名称,我们称之为 "ll_project",以便与启动项目时使用的名称保持一致❶。我们还需要指定使用的 Python 版本(本文撰写时为 3.10)。您可以在 https://docs.platform.sh/languages/python.xhtml 上找到支持版本的列表。

接下来是标有关系的部分,其中定义了项目需要的其他服务❷。这里唯一的关系是 Postgres 数据库。之后是网络部分❸。commands:start 部分告诉 Platform.sh 使用哪个进程来处理接收到的请求。这里我们指定由 gunicorn 处理请求 ❹。这条命令取代了我们在本地使用的 python manage.py runserver 命令。

locations 部分告诉 Platform.sh 向何处发送接收到的请求❺。大多数请求都会传递给 gunicorn;我们的 urls.py 文件会告诉 gunicorn 如何处理这些请求。静态文件请求将单独处理,每小时刷新一次。最后一行显示,我们请求 Platform.sh 服务器上的 512MB 磁盘空间❻。

platform.app.yaml 的其余部分如下:
--snip--
disk: 512

# Set a local read/write mount for logs.
❶ mounts:
        "logs":
            source: local
            source_path: logs

# The hooks executed at various points in the lifecycle of the application.
❷ hooks:
      build: |
❸         pip install --upgrade pip
          pip install -r requirements.txt
          pip install -r requirements_remote.txt

          mkdir logs
❹         python manage.py collectstatic
          rm -rf logs
❺    deploy: |
          python manage.py migrate

挂载部分❶ 可让我们定义项目运行时可读写数据的目录。该部分定义了已部署项目的 logs/ 目录。

钩子部分❷ 定义了在部署过程中不同阶段采取的行动。在构建部分,我们安装在实时环境❸ 中为项目提供服务所需的所有软件包。我们还会运行 collectstatic ❹,它将项目所需的所有静态文件收集到一处,以便高效地提供服务。

最后,在部署部分❺,我们指定每次部署项目时都要运行迁移。在一个简单的项目中,如果没有任何更改,这一点不会产生任何影响。

另外两个配置文件要短得多,现在我们就来编写它们。

routes.yaml 配置文件

路由是服务器处理请求的路径。Platform.sh 收到请求后,需要知道该将请求发送到哪里。

在 manage.py 的同一目录下新建一个名为 .platform 的文件夹。确保名称开头包含点。在该文件夹中,创建一个名为 routes.yaml 的文件,并输入以下内容:

.platform/routes.yaml
# Each route describes how an incoming URL will be processed by Platform.sh.

"https://{default}/":
    type: upstream
    upstream: "ll_project:http"

"https://www.{default}/":
    type: redirect
    to: "https://{default}/"

该文件可确保 https://project_url.com 和 www.project_url.com 等请求都被路由到同一个地方。

services.yaml 配置文件

最后一个配置文件指定了项目运行所需的服务。将此文件与 routes.yaml 文件一起保存在 .platform/ 目录中:

platform/routes.yaml
# Each service listed will be deployed in its own container as part of your
# Platform.sh project.

db:
    type: postgresql:12
    disk: 1024

该文件定义了一个服务,即 Postgres 数据库。

修改 Platform.sh 的 settings.py

现在,我们需要在 settings.py 的末尾添加一个部分,以修改 Platform.sh 环境的一些设置。将此代码添加到 settings.py 的末尾:

settings.py
--snip--
# Platform.sh settings.
from platformshconfig import Config # 1

config = Config()
if config.is_valid_platform(): # 2
    ALLOWED_HOSTS.append('.platformsh.site') # 3

    if config.appDir: # 4
        STATIC_ROOT = Path(config.appDir) / 'static'
    if config.projectEntropy: # 5
        SECRET_KEY = config.projectEntropy

    if not config.in_build():
        db_settings = config.credentials('database') # 6
        DATABASES = {
            'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': db_settings['path'],
            'USER': db_settings['username'],
            'PASSWORD': db_settings['password'],
            'HOST': db_settings['host'],
            'PORT': db_settings['port'],
            },
        }

我们通常将导入语句放在模块的开头,但在这种情况下,将所有远程特定设置放在一个部分会很有帮助。这里我们从 platformshconfig ❶ 中导入 Config,它有助于确定远程服务器上的设置。只有当 config.is_valid_platform() 方法返回 True ❷,表明设置正在 Platform.sh 服务器上使用时,我们才修改设置。

我们修改 ALLOWED_HOSTS,以允许项目由 .platformsh.site ❸ 结尾的主机提供服务。所有部署到免费层的项目都将使用该主机。如果在部署的应用程序目录❹ 中加载设置,我们会设置 STATIC_ROOT,以便正确提供静态文件。我们还在远程服务器 ❺ 上设置了更安全的 SECRET_KEY。

最后,我们配置生产数据库 ❻。只有在构建过程结束、项目正在运行时,才会设置该数据库。这里的所有内容都是让 Django 与 Platform.sh 为项目设置的 Postgres 服务器进行对话所必需的。

使用 Git 跟踪项目的文件

正如第 17 章所述,Git 是一种版本控制程序,每次成功实现一个新功能时,都能为项目中的代码拍摄快照。例如,在开发新功能时不小心引入了一个 Bug,如果出了什么问题,你可以很容易地返回到上次的项目快照。每个快照称为一次提交。

使用 Git,您可以尝试实现新功能,而不必担心会破坏您的项目。在部署到实时服务器时,需要确保部署的是项目的工作版本。要了解有关 Git 和版本控制的更多信息,请参阅附录 D。

安装 Git

您的系统可能已经安装了 Git。要知道这一点,请打开一个新的终端窗口,然后发出 git — version 命令:

(ll_env)learning_log$ git --version
git version 2.30.1 (Apple Git-130)

如果收到 Git 未安装的提示,请参阅附录 D 中的安装说明。

配置 Git

Git 会记录谁修改了项目,即使只有一个人在做项目。为此,Git 需要知道你的用户名和电子邮件地址。你必须提供一个用户名,但也可以为你的实践项目创建一个电子邮件地址:

(ll_env)learning_log$ git config --global user.name "eric"
(ll_env)learning_log$ git config --global user.email "eric@example.com"

如果您忘记了这一步,Git 会在您第一次提交时提示您提供这些信息。

ignoring 文件

我们不需要 Git 跟踪项目中的每个文件,所以我们要让它忽略一些文件。在包含 manage.py 的文件夹中创建一个名为 .gitignore 的文件。注意,这个文件名以点开头,没有扩展名。下面是 .gitignore 中的代码:

.gitignore
ll_env/
__pycache__/
*.sqlite3

我们告诉 Git 忽略整个 ll_env 目录,因为我们可以随时自动重新创建它。我们也不跟踪 __pycache__ 目录,该目录包含执行 .py 文件时自动创建的 .pyc 文件。我们不跟踪本地数据库的更改,因为这是一个坏习惯:如果你在服务器上使用 SQLite,当你把项目推送到服务器时,可能会不小心用本地测试数据库覆盖实时数据库。*.sqlite3 中的星号会告诉 Git 忽略任何以 .sqlite3 结尾的文件。

如果使用的是 macOS,请在 .gitignore 文件中添加 .DS_Store。这是一个存储 macOS 上文件夹设置信息的文件,与本项目无关。

提交项目

我们需要为学习日志初始化一个 Git 仓库,将所有必要的文件添加到该仓库,并提交项目的初始状态。下面是具体操作:

❶ (ll_env)learning_log$ git init
Initialized empty Git repository in /Users/eric/.../learning_
log/.git/
❷ (ll_env)learning_log$ git add .
❸ (ll_env)learning_log$ git commit -am "Ready for deployment t
o Platform.sh."
[main (root-commit) c7ffaad] Ready for deployment to Platfor
m.sh.
42 files changed, 879 insertions(+)
create mode 100644 .gitignore
create mode 100644 .platform.app.yaml
--snip--
create mode 100644 requirements_remote.txt
❹ (ll_env)learning_log$ git status
On branch main
nothing to commit, working tree clean
(ll_env)learning_log$

我们使用 git init 命令在包含学习日志 ❶ 的目录中初始化一个空仓库。然后我们使用 git add .命令,将所有未被忽略的文件添加到仓库❷。(不要忘了点。)接下来,我们发布 git commit -am "commit message" 命令:-a 标志告诉 Git 将所有更改的文件都包含在这次提交中,-m 标志告诉 Git 记录一条日志信息 ❸。

发出 git status 命令❹,表示我们在主分支上,工作树是干净的。无论何时将项目推送到远程服务器,这都是你想要看到的状态。

在 Platform.sh 上创建项目

此时,Learning Log 项目仍在本地系统上运行,并已配置为可在远程服务器上正常运行。我们将使用 Platform.sh CLI 在服务器上创建一个新项目,然后将项目推送到远程服务器。

确保在终端中的 learning_log/ 目录下,发出以下命令:

(ll_env)learning_log$ platform login
Opened URL: http://127.0.0.1:5000
Please use the browser to log in.
--snip--
❶ Do you want to create an SSH configuration file automaticall
y? [Y/n] Y

该命令将打开一个浏览器标签页,在此登录。登录后,可以关闭浏览器标签页并返回终端。如果系统提示创建 SSH 配置文件❶,请输入 Y,以便稍后连接远程服务器。

现在我们将创建一个项目。输出内容很多,因此我们将分段查看创建过程。首先发出创建命令:

(ll_env)learning_log$ platform create
* Project title (--title)
Default: Untitled Project

❶ > ll_project

* Region (--region)
The region where the project will be hosted
--snip--
[us-3.platform.sh] Moses Lake, United States (AZURE) [514 g
C02eq/kWh]
❷ > us-3.platform.sh
* Plan (--plan)
Default: development
Enter a number to choose:
[0] development
--snip--
❸ > 0

* Environments (--environments)
The number of environments
Default: 3
❹ > 3

* Storage (--storage)
The amount of storage per environment, in GiB
Default: 5
❺ > 5

第一个提示询问项目的名称 ❶,因此我们使用 ll_project。下一个提示询问我们希望服务器位于哪个地区 ❷。选择离你最近的服务器;对我来说,就是 us-3.platform.sh。对于其他提示,你可以接受默认值:最低开发计划的服务器❸,项目的三个环境❹,以及整个项目的 5GB 存储空间❺。

还有三个提示需要回答:

Default branch (--default-branch)
The default Git branch name for the project (the production e
nvironment)
Default: main
❶ > main

Git repository detected: /Users/eric/.../learning_log
❷ Set the new project ll_project as the remote for this repository? [Y/n] Y

The estimated monthly cost of this project is: $10 USD
❸ Are you sure you want to continue? [Y/n] Y

The Platform.sh Bot is activating your project
  ▀▄   ▄▀
█▄█▀███▀█▄█
▀█████████▀
 ▄▀     ▀▄
The project is now ready!

一个 Git 仓库可以有多个分支;Platform.sh 会询问我们项目的默认分支是否为 main ❶。然后它会询问我们是否要将本地项目的仓库连接到远程仓库 ❷。最后,我们会被告知,如果在免费试用期❸ 之后继续运行该项目,每月将花费约 10 美元。如果你还没有输入信用卡,就不必担心这笔费用。如果您在没有添加信用卡的情况下超过了免费试用期的限制,Platform.sh 会简单地暂停您的项目。

推送到 Platform.sh

在看到项目的实时版本之前,最后一步是将代码推送到远程服务器。为此,请执行以下命令:

(ll_env)learning_log$ platform push
❶ Are you sure you want to push to the main (production) branch? [Y/n] Y
--snip--
The authenticity of host 'git.us-3.platform.sh (...)' can't be established.
RSA key fingerprint is SHA256:Tvn...7PM
❷ Are you sure you want to continue connecting (yes/no/[fingerprint])? Y
Pushing HEAD to the existing environment main
--snip--
To git.us-3.platform.sh:3pp3mqcexhlvy.git
* [new branch] HEAD -> main

当你发出 platform push 命令时,系统会再次要求你确认是否要推送项目 ❶。如果这是你第一次连接网站 ❷,你可能还会看到一条关于 Platform.sh 真实性的信息。在每个提示下输入 Y,就会看到大量输出滚动显示。这些输出结果一开始可能会让人一头雾水,但如果出了什么问题,这些输出结果在故障排除过程中会非常有用。如果略微浏览一下输出,就会发现 Platform.sh 安装了必要的软件包、收集了静态文件、应用了迁移并为项目设置了 URL。

您可能会看到一些很容易诊断的错误,比如某个配置文件中的错别字。如果出现这种情况,请在文本编辑器中修正错误,保存文件,然后重新发布 git commit 命令。然后就可以再次运行 platform push 了。

查看实时项目

推送完成后,就可以打开项目了:

(ll_env)learning_log$ platform url
Enter a number to open a URL
[0] https://main-bvxea6i-wmye2fx7wwqgu.us-3.platformsh.site/
--snip--
> 0

platform url 命令会列出与已部署项目相关联的 URL;你可以选择多个 URL,这些 URL 对你的项目都有效。选择其中一个,你的项目就会在新的浏览器标签页中打开!这看起来就像我们在本地运行的项目一样,但你可以将此 URL 分享给世界上的任何人,他们都可以访问并使用你的项目。

使用试用账户部署项目时,如果页面加载时间有时比平时长,请不要感到惊讶。在大多数托管平台上,闲置的免费资源通常会被暂停,只有在有新请求时才会重新启动。在付费托管计划中,大多数平台的响应速度要快得多。

完善 Platform.sh 部署

现在,我们将通过创建超级用户来完善部署,就像在本地所做的那样。我们还将把 DEBUG 设置改为 False,这样错误信息就不会向用户显示任何可能用于攻击服务器的额外信息,从而使项目更加安全。

在 Platform.sh 上创建超级用户

实时项目的数据库已经建立,但完全是空的。我们之前创建的所有用户都只存在于本地版本的项目中。

为了在项目的实时版本中创建超级用户,我们将启动 SSH(安全套接字外壳)会话,在远程服务器上运行管理命令:

(ll_env)learning_log$ platform environment:ssh
___ _ _ __ _
| _ \ |__ _| |_ / _|___ _ _ _ __ __| |_
| _/ / _` | _| _/ _ \ '_| ' \ _(_-< ' \
|_| |_\__,_|\__|_| \___/_| |_|_|_(_)__/_||_|
Welcome to Platform.sh.
❶ web@ll_project.0:~$ ls
accounts learning_logs ll_project logs manage.py require
ments.txt
requirements_remote.txt static
❷ web@ll_project.0:~$ python manage.py createsuperuser
❸ Username (leave blank to use 'web'): ll_admin_live
Email address:
Password:
Password (again):
Superuser created successfully.
❹ web@ll_project.0:~$ exit
logout
Connection to ssh.us-3.platform.sh closed.
❺ (ll_env)learning_log$

首次运行 platform environment:ssh 命令时,您可能会收到另一条提示信息,说明该主机的真实性。如果看到这条信息,请输入 Y,然后就可以登录远程终端会话了。

运行 ssh 命令后,你的终端就会像远程服务器上的终端一样运行。请注意,你的提示已发生变化,显示你正处于与名为 ll_project ❶的项目相关联的网络会话中。如果你发出 ls 命令,就会看到已推送到 Platform.sh 服务器的文件。

发出与第 18 章❷ 中相同的 createsuperuser 命令。这一次,我输入了一个管理员用户名 ll_admin_live,它与我在本地使用的用户名不同❸。完成远程终端会话后,输入退出命令 ❹。提示符会显示你又在本地系统中工作了 ❺。

现在,你可以在实时应用程序的 URL 末尾添加 /admin/,并登录管理站点。如果其他人已经开始使用你的项目,请注意你可以访问他们的所有数据!认真履行这一职责,用户就会继续信任你,将他们的数据交给你。

Windows 用户将使用此处显示的相同命令(如 ls 代替 dir),因为你是通过远程连接运行 Linux 终端。

确保现场项目的安全

我们项目目前的部署方式存在一个明显的安全问题:设置.py 中的 DEBUG = True 设置会在错误发生时提供调试信息。在开发项目时,Django 的错误页面会提供重要的调试信息;但是,如果在实时服务器上启用这些选项,它们就会向攻击者提供过多的信息。

要了解这种情况有多糟糕,请访问已部署项目的主页。登录用户账户,在主页 URL 的末尾添加 /topics/999/。如果你没有创建成千上万的主题,你应该会在 /topics/999/ 看到一个显示 DoesNotExist 消息的页面。 如果你向下滚动,你应该会看到一大堆关于项目和服务器的信息。你不会想让用户看到这些信息,当然也不会想让任何有兴趣攻击网站的人看到这些信息。

我们可以在 settings.py 中仅适用于项目部署版本的部分设置 DEBUG = False,从而防止在实时网站上显示这些信息。这样,你将继续在本地看到调试信息,因为这些信息是有用的,但不会显示在实时网站上。

在文本编辑器中打开 settings.py,在修改 Platform.sh 设置的部分添加一行代码:

settings.py
--snip--
if config.is_valid_platform():
    ALLOWED_HOSTS.append('.platformsh.site')
    DEBUG = False
    --snip--

为项目部署版本设置配置的所有工作都已见成效。当我们要调整项目的实时版本时,只需更改之前设置的配置的相关部分即可。

提交和推送更改

现在,我们需要提交对 settings.py 所做的更改,并将更改推送到 Platform.sh。下面的终端会话显示了这一过程的第一部分:

❶ (ll_env)learning_log$ git commit -am "Set DEBUG False on live site."
[main d2ad0f7] Set DEBUG False on live site.
1 file changed, 1 insertion(+)
❷ (ll_env)learning_log$ git status
On branch main
nothing to commit, working tree clean
(ll_env)learning_log$

我们发出 git commit 命令,并附上简短而有描述性的提交信息❶。记住 -am 标志,它能确保 Git 提交所有有改动的文件,并记录日志信息。Git 会识别出有一个文件发生了改动,并将此改动提交到版本库中。

运行 git status 显示,我们正在版本库的主分支上工作,现在没有新的改动需要提交❷。在推送到远程服务器之前,检查状态很重要。如果你没有看到干净的状态,那么就说明有些变更还没有提交,这些变更也不会被推送到服务器上。如果你不确定如何解决这个问题,可以阅读附录 D 以更好地理解如何使用 Git。

现在,让我们把更新后的版本库推送到 Platform.sh:

(ll_env)learning_log$ platform push
Are you sure you want to push to the main (production) branc
h? [Y/n] Y
Pushing HEAD to the existing environment main
--snip--
To git.us-3.platform.sh:wmye2fx7wwqgu.git
fce0206..d2ad0f7 HEAD -> main
(ll_env)learning_log$

Platform.sh 会识别版本库已更新,并重建项目以确保所有更改都已考虑在内。它不会重建数据库,因此我们不会丢失任何数据。

为确保更改生效,请再次访问 /topics/999/ URL。你应该只看到服务器错误 (500) 消息,而根本看不到关于项目的敏感信息。

创建自定义错误页面

在第 19 章中,我们配置了学习日志,如果用户请求不属于自己的主题或条目,学习日志会返回 404 错误。现在你也看到了 500 服务器错误。

404 错误通常意味着你的 Django 代码是正确的,但请求的对象不存在。500 错误通常意味着您编写的代码有误,例如 views.py 中的函数出错。Django 目前会在这两种情况下返回相同的通用错误页面,但我们可以编写自己的 404 和 500 错误页面模板,使其与学习日志的整体外观相匹配。这些模板属于根模板目录。

制作自定义模板

在 learning_log 文件夹中新建一个名为 templates 的文件夹。然后新建一个名为 404.xhtml 的文件;该文件的路径应为 learning_log/templates/404.xhtml。下面是该文件的代码:

404.xhtml
{% extends "learning_logs/base.xhtml" %}

{% block page_header %}
<h2>The item you requested is not available. (404)</h2>
{% endblock page_header %}

这个简单的模板提供了通用的 404 错误页面信息,但其样式与网站的其他部分相匹配。

使用以下代码创建另一个名为 500.xhtml 的文件:

500.xhtml
{% extends "learning_logs/base.xhtml" %}

{% block page_header %}
<h2>There has been an internal error. (500)</h2>
{% endblock page_header %}

这些新文件需要对 settings.py 稍作修改。

settings.py
--snip--
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTem
        plates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,
        --snip--
    },
]
--snip--

这一更改会告诉 Django 在根模板目录中查找错误页面模板和其他任何与特定应用程序无关的模板。

将更改推送到 Platform.sh

现在,我们需要提交刚才所做的更改,并将其推送至 Platform.sh:

❶ (ll_env)learning_log$ git add .
❷ (ll_env)learning_log$ git commit -am "Added custom 404 and 5
00 error pages."
3 files changed, 11 insertions(+), 1 deletion(-)
create mode 100644 templates/404.xhtml
create mode 100644 templates/500.xhtml
❸ (ll_env)learning_log$ platform push
--snip--
To git.us-3.platform.sh:wmye2fx7wwqgu.git
d2ad0f7..9f042ef HEAD -> main
(ll_env)learning_log$

我们发布 git add .命令❶,因为我们在项目中创建了一些新文件。然后提交更改❷,并将更新后的项目推送到 Platform.sh ❸。

现在,当错误页面出现时,它的样式应该与网站的其他部分相同,这样当错误出现时,用户体验会更流畅。

持续开发

在首次推送到实时服务器后,你可能想进一步开发学习日志,或者想开发自己的项目进行部署。在这样做时,更新项目的流程相当一致。

首先,你要对本地项目进行必要的修改。如果改动后产生了新文件,则使用 git add 命令将这些文件添加到 Git 仓库(确保在命令末尾加上圆点)。任何需要迁移数据库的改动都需要这条命令,因为每次迁移都会生成一个新的迁移文件。

其次,使用 git commit -am "commit message" 将更改提交到版本库。然后使用 platform push 命令将更改推送到 Platform.sh。访问您的实时项目,确保您希望看到的更改已经生效。

在此过程中很容易出错,所以出错时不要惊讶。如果代码无法运行,请检查您所做的工作,并尝试找出错误所在。如果找不到错误或不知道如何纠正,请参考附录 C 中的求助建议。不要羞于寻求帮助:每个人都是通过提出与你可能提出的相同的问题来学习构建项目的,因此有人会很乐意帮助你。解决出现的每一个问题都有助于稳步提高你的技能,直到你能构建出有意义、可靠的项目,并能回答其他人的问题。

删除 Platform.sh 上的项目

对同一个项目或一系列小项目进行多次部署,以掌握部署的窍门,是一种很好的做法。但你需要知道如何删除已部署的项目。此外,Platform.sh 还限制了免费托管项目的数量,你也不想让实践项目弄乱你的账户。

您可以使用 CLI 删除项目:

(ll_env)learning_log$ platform project:delete

系统会要求您确认是否要采取这一破坏性操作。按照提示操作,你的项目就会被删除。

命令 platform create 还为本地 Git 仓库提供了 Platform.sh 服务器上远程仓库的引用。你也可以从命令行中删除这个远程仓库:

(ll_env)learning_log$ git remote
platform
(ll_env)learning_log$ git remote remove platform

git remote 命令会列出与当前版本库关联的所有远程 URL 的名称。git remote remove remote_name 命令会从本地版本库中删除这些远程 URL。

你也可以登录 Platform.sh 网站,访问 http s://console.platform.sh 上的控制面板来删除项目资源。此页面列出了所有活动项目。单击项目框中的三个点,然后单击编辑计划。这是项目的定价页面;单击页面底部的删除项目按钮,您将看到一个确认页面,可以在此完成删除操作。即使你使用 CLI 删除了项目,最好还是熟悉一下你部署的任何托管提供商的仪表板。

删除 Platform.sh 上的项目对本地版本的项目没有任何影响。如果没有人使用过你部署的项目,而你只是在练习部署过程,那么删除 Platform.sh 上的项目并重新部署是完全合理的。但要注意,如果项目停止运行,可能是遇到了主机的自由层限制。

亲自试试

20-3. 实时博客:将您正在开发的 Blog 项目部署到 Platform.sh。确保将 DEBUG 设为 False,这样用户就不会在出错时看到完整的 Django 错误页面。

20-4. 扩展学习日志:为学习日志添加一项功能,并将更改推送到实时部署中。尝试一个简单的更改,例如在主页上写更多关于项目的内容。然后尝试添加一个更高级的功能,例如让用户可以选择将主题公开。这需要在主题模型中添加名为 public 的属性(默认设置为 False),并在 new_topic 页面添加表单元素,允许用户将主题从私有改为公开。然后,您需要迁移项目并修改 views.py,以便未认证用户也能看到任何公开的主题。

总结

在本章中,您将学习如何使用 Bootstrap 库和 django-bootstrap5 应用程序为您的项目打造简洁而专业的外观。有了 Bootstrap,您选择的样式几乎可以在人们访问项目时使用的任何设备上一致运行。

您了解了 Bootstrap 的模板,并使用导航栏静态模板为学习日志创建了简单的外观和感觉。你使用了跳线来突出主页的信息,并学会了如何统一网站中所有页面的样式。

在项目的最后一部分,你们学习了如何将项目部署到远程服务器上,以便任何人都能访问。你创建了一个 Platform.sh 账户,并安装了一些有助于管理部署过程的工具。你使用 Git 将工作项目提交到版本库,然后将版本库推送到 Platform.sh 上的远程服务器。最后,你学会了通过在实时服务器上设置 DEBUG = False 来开始保护应用程序的安全。你还制作了自定义错误页面,这样就能很好地处理不可避免的错误。

现在,您已经完成了学习日志,可以开始构建自己的项目了。从简单的开始,在增加复杂性之前确保项目能正常运行。祝你学习愉快,项目顺利!