Django 教程第 11 部分:将 Django 部署到生产环境

现在你已经创建(并测试)了一个很棒的 LocalLibrary 网站,你将希望把它安装到一个公共的 Web 服务器上,以便图书馆工作人员和成员可以通过互联网访问它。本文概述了如何找到一个主机来部署你的网站,以及你需要做些什么才能让你的网站准备好投入生产。

先决条件 完成所有之前的教程主题,包括 Django 教程第 10 部分:测试 Django Web 应用程序
目标 了解在哪里以及如何将 Django 应用程序部署到生产环境。

概述

网站完成后(或“足够”完成以开始公开测试),你需要将其托管在比个人开发计算机更公开、更易访问的地方。

到目前为止,你一直在开发环境中工作,使用 Django 开发 Web 服务器将你的网站共享到本地浏览器/网络,并使用(不安全的)开发设置运行你的网站,这些设置会公开调试和其他私有信息。在你可以将网站托管到外部之前,你首先需要

  • 对你的项目设置进行一些更改。
  • 选择一个环境来托管 Django 应用程序。
  • 选择一个环境来托管任何静态文件。
  • 为你的网站设置一个生产级基础设施。

本教程提供了一些关于选择托管网站的选项的指导,简要概述了你需要做些什么才能让你的 Django 应用程序准备好投入生产,以及将 LocalLibrary 网站安装到 Railway 云托管服务的示例。

什么是生产环境?

生产环境是服务器计算机提供的环境,你将在其中运行你的网站以供外部使用。该环境包括

  • 运行网站的计算机硬件。
  • 操作系统(例如 Linux、Windows)。
  • 在你的网站之上编写的编程语言运行时和框架库。
  • 用于提供页面和其他内容的 Web 服务器(例如 Nginx、Apache)。
  • 将“动态”请求在你的 Django 网站和 Web 服务器之间传递的应用程序服务器。
  • 你的网站依赖的数据库。

注意:取决于你的生产环境的配置方式,你可能还需要反向代理、负载均衡器等等。

服务器计算机可以位于你的场所并通过快速链接连接到互联网,但使用位于“云”中的计算机更为常见。这实际上意味着你的代码是在你的托管公司的数据中心(或可能是“虚拟”计算机)中的某些远程计算机上运行的。远程服务器通常会提供一定级别的计算资源(CPU、RAM、存储内存等)和互联网连接,并收取一定的费用。

这种远程可访问的计算/网络硬件被称为基础设施即服务 (IaaS)。许多 IaaS 供应商提供预安装特定操作系统的选项,你必须在该操作系统上安装生产环境的其他组件。其他供应商允许你选择功能更全面的环境,可能包括完整的 Django 和 Web 服务器设置。

注意:预构建的环境可以使你的网站设置非常容易,因为它们减少了配置,但可用的选项可能会限制你使用不熟悉的服务器(或其他组件),并且可能基于旧版本的 OS。通常,最好自己安装组件,这样你就可以获得你想要的组件,并且当你需要升级系统的一部分时,你就会知道从哪里开始!

其他托管提供商在平台即服务 (PaaS) 产品中支持 Django。在这种类型的托管中,你不需要担心你的大部分生产环境(Web 服务器、应用程序服务器、负载均衡器),因为主机平台会为你处理这些环境——以及你需要做的大部分事情才能扩展你的应用程序。这使得部署非常容易,因为你只需要专注于你的 Web 应用程序,而无需关注其他服务器基础设施。

一些开发人员会选择 IaaS 提供的更高的灵活性,而不是 PaaS,而另一些开发人员则会欣赏 PaaS 减少的维护开销和更轻松的扩展。在开始时,在 PaaS 系统上设置你的网站要容易得多,因此我们将在本教程中执行此操作。

注意:如果你选择了一个 Python/Django 友好的托管提供商,他们应该提供有关如何使用 Web 服务器、应用程序服务器、反向代理等的不同配置设置 Django 网站的说明。(如果你选择了一个 PaaS,这将无关紧要)。例如,在 Digital Ocean Django 社区文档 中,有许多针对各种配置的分步指南。

选择托管提供商

许多托管提供商都以积极支持或与 Django 协同工作而闻名,包括:HerokuDigital OceanRailwayPython AnywhereAmazon Web ServicesAzureGoogle CloudHetznerVultr Cloud Compute——仅举几例。这些供应商提供不同类型的环境(IaaS、PaaS)以及不同价格的不同级别的计算和网络资源。

在选择主机时需要考虑的一些事项

  • 你的网站可能有多繁忙,以及满足这一需求所需的成本和计算资源。
  • 水平扩展(添加更多机器)和垂直扩展(升级到更强大的机器)的支持级别以及这样做的成本。
  • 供应商拥有数据中心的位置,以及访问速度最快的区域。
  • 主机的历史正常运行时间和停机时间性能。
  • 用于管理网站的工具——它们是否易于使用,以及它们是否安全(例如 SFTP 与 FTP)。
  • 用于监控你的服务器的内置框架。
  • 已知的限制。某些主机会故意阻止某些服务(例如电子邮件)。其他主机只提供某些价格级别的“直播时间”,或只提供少量存储空间。
  • 额外优势。一些供应商会提供免费的域名和对 TLS 证书的支持,否则你需要付费才能获得这些证书。
  • 你依赖的“免费”层是否会随着时间的推移而过期,以及迁移到更昂贵层的价格是否意味着一开始就应该使用其他服务!

好消息是,在开始时,有很多网站提供“免费”计算环境,这些环境旨在用于评估和测试。这些环境通常是资源受限/有限的环境,你确实需要意识到,它们可能会在一些入门期后过期,或者有其他限制。然而,它们非常适合在托管环境中测试低流量网站,并且可以轻松迁移到付费获取更多资源,当你的网站变得更繁忙时。此类别的热门选择包括 Vultr Cloud ComputePython AnywhereAmazon Web ServicesMicrosoft Azure 等等。

大多数供应商还提供“基本”层,旨在用于小型生产网站,并且提供更实用的计算能力和更少的限制。RailwayHerokuDigital Ocean 是流行的托管提供商的示例,它们提供相对便宜的基本计算层(每月 5 到 10 美元)。

注意:请记住,价格不是唯一的选择标准。如果你的网站成功,可扩展性可能是最重要的考虑因素。

准备网站发布

使用django-adminmanage.py 工具创建的 Django 骨架网站 被配置为简化开发。许多 Django 项目设置(在settings.py 中指定)应该在生产环境中有所不同,这可能是出于安全或性能方面的考虑。

注意:通常会为生产环境使用单独的settings.py 文件,或者有条件地从单独的文件或环境变量导入敏感设置。然后应保护此文件,即使其余源代码在公共存储库中可用。

你必须检查的关键设置是

  • DEBUG。这应该在生产环境中设置为False (DEBUG = False)。这会阻止敏感/机密的调试跟踪和变量信息显示。
  • SECRET_KEY。这是一个用于 CSRF 保护等的大型随机值。重要的是,在生产环境中使用的密钥不在源代码控制中,也不在生产服务器之外访问。

Django 文档建议最好从环境变量加载秘密信息,或者从仅服务器文件读取。让我们更改LocalLibrary 应用程序,以便如果定义了环境变量,我们从环境变量中读取我们的SECRET_KEYDEBUG 变量,回退到在根目录中定义的.env 文件中的值,最后使用配置文件中的默认值。这非常灵活,因为它允许任何由托管服务器支持的配置。

为了从文件读取环境值,我们将使用 python-dotenv。这是一个用于从文件读取键值对并将其用作环境变量的库,但前提是相应的环境变量没有定义。

将库安装到你的虚拟环境中,如所示(并更新你的requirements.txt 文件)

bash
pip3 install python-dotenv

然后打开/locallibrary/settings.py,在定义BASE_DIR 之后插入以下代码,但在安全警告之前:# SECURITY WARNING: keep the secret key used in production secret!

py
# Support env variables from .env file if defined
import os
from dotenv import load_dotenv
env_path = load_dotenv(os.path.join(BASE_DIR, '.env'))
load_dotenv(env_path)

这将从 Web 应用程序的根目录加载.env 文件。在文件中定义为KEY=VALUE 的变量在os.environ.get('<KEY>'', '<DEFAULT VALUE>') 中使用该键时导入,如果已定义。

注意:添加到.env 的任何值都可能是秘密!你不能将其保存到 GitHub,并且应该将.env 添加到你的.gitignore 文件中,以便不会意外添加它。

接下来,禁用原始的SECRET_KEY 配置,并添加如下所示的新行。在开发过程中,不会为密钥指定任何环境变量,因此将使用默认值(在这里使用什么密钥并不重要,或者密钥是否“泄漏”,因为你不会在生产环境中使用它)。

python
# SECURITY WARNING: keep the secret key used in production secret!
# SECRET_KEY = 'django-insecure-&psk#na5l=p3q8_a+-$4w1f^lt3lx1c@d*p4x$ymm_rn7pwb87'
import os
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'django-insecure-&psk#na5l=p3q8_a+-$4w1f^lt3lx1c@d*p4x$ymm_rn7pwb87')

然后注释掉现有的DEBUG 设置,并添加如下所示的新行。

python
# SECURITY WARNING: don't run with debug turned on in production!
# DEBUG = True
DEBUG = os.environ.get('DJANGO_DEBUG', '') != 'False'

DEBUG 的值为True 为默认值,但只有在DJANGO_DEBUG 环境变量的值设置为FalseDJANGO_DEBUG=False.env 文件中设置时,它才会为False。请注意,环境变量是字符串,而不是 Python 类型。因此,我们需要比较字符串。将DEBUG 变量设置为False 的唯一方法是实际将其设置为字符串False

您可以通过在 Linux 上执行以下命令将环境变量设置为“False”。

bash
export DJANGO_DEBUG=False

您可能想要更改的设置的完整清单在 部署清单(Django 文档)中提供。您也可以使用以下终端命令列出其中一些

python
python3 manage.py check --deploy

Gunicorn

Gunicorn 是一个纯 Python HTTP 服务器,通常用于为 Django WSGI 应用程序提供服务。

虽然我们不需要在开发过程中使用 *Gunicorn* 为 LocalLibrary 应用程序提供服务,但我们将本地安装它,以便在应用程序部署时成为我们 需求 的一部分。

首先,确保您在您 设置开发环境 时创建的 Python 虚拟环境中(使用 workon [name-of-virtual-environment] 命令)。然后使用 *pip* 在命令行上本地安装 *Gunicorn*。

bash
pip3 install gunicorn

数据库配置

SQLite 是您一直在用于开发的默认 Django 数据库,对于小型到中型网站来说是一个合理的选择。不幸的是,它无法在某些流行的托管服务(例如 Heroku)上使用,因为它们不在应用程序环境中提供持久数据存储(SQLite 的一项要求)。虽然这可能不会影响我们示例部署,但我们将向您展示另一种方法,该方法适用于 Railway、Heroku 和其他一些服务。

这种方法是使用一个在互联网上的某个位置的自己的进程中运行的数据库,并使用作为环境变量传递的地址由 Django 库应用程序访问。在这种情况下,我们将使用一个也托管在 Railway 上的 Postgres 数据库,但您可以使用任何您喜欢的数据库托管服务。

数据库连接信息将使用名为 DATABASE_URL 的环境变量提供给 Django。与其将此信息硬编码到 Django 中,我们将使用 dj-database-url 包来解析 DATABASE_URL 环境变量并自动将其转换为 Django 期望的配置格式。除了安装 *dj-database-url* 包之外,我们还需要安装 psycopg2,因为 Django 需要它与 Postgres 数据库进行交互。

dj-database-url

*dj-database-url* 用于从环境变量中提取 Django 数据库配置。

在本地安装它,以便它成为我们在部署服务器上设置的 需求 的一部分。

bash
pip3 install dj-database-url

settings.py

打开 **locallibrary/settings.py** 并将以下配置复制到文件底部。

python
# Update database configuration from $DATABASE_URL environment variable (if defined)
import dj_database_url

if 'DATABASE_URL' in os.environ:
    DATABASES['default'] = dj_database_url.config(
        conn_max_age=500,
        conn_health_checks=True,
    )

如果设置了环境变量,Django 现在将使用 DATABASE_URL 中的数据库配置;否则,它使用默认的 SQLite 数据库。值 conn_max_age=500 使连接持久化,这比在每个请求周期重新创建连接效率高得多(这是可选的,如果需要可以删除)。

psycopg2

Django 需要 *psycopg2* 来使用 Postgres 数据库。在本地安装它,以便它成为我们在 Railway 上设置的远程服务器的 需求 的一部分。

bash
pip3 install psycopg2-binary

请注意,Django 默认情况下会在开发期间使用 SQLite 数据库,除非设置了 DATABASE_URL。您可以完全切换到 Postgres 并使用同一个托管数据库进行开发和生产,方法是在您的开发环境中设置同一个环境变量(Railway 使得轻松使用相同的环境进行生产和开发)。或者,您也可以在本地计算机上安装和使用 自托管的 Postgres 数据库

在生产环境中提供静态文件

在开发过程中,我们使用 Django 和 Django 开发 Web 服务器来为我们的动态 HTML 和静态文件(CSS、JavaScript 等)提供服务。对于静态文件来说,这是低效的,因为请求必须通过 Django,即使 Django 没有对它们进行任何操作。虽然这在开发过程中无关紧要,但如果我们在生产环境中使用相同的方法,它会对性能产生重大影响。

在生产环境中,我们通常将静态文件与 Django Web 应用程序分开,从而更容易直接从 Web 服务器或内容交付网络 (CDN) 提供服务。

重要的设置变量是

  • STATIC_URL:这是提供静态文件的基 URL 位置,例如在 CDN 上。
  • STATIC_ROOT:这是 Django 的 *collectstatic* 工具将收集我们模板中引用的所有静态文件的目录的绝对路径。收集后,这些文件可以作为一个组上传到要托管文件的任何位置。
  • STATICFILES_DIRS:这列出了 Django 的 *collectstatic* 工具应该搜索静态文件的其他目录。

Django 模板引用相对于 static 标签的静态文件位置(您可以在 Django 教程第 5 部分:创建我们的主页 中定义的基模板中看到这一点),它反过来映射到 STATIC_URL 设置。因此,静态文件可以上传到任何主机,您可以更新您的应用程序以使用此设置找到它们。

*collectstatic* 工具用于将静态文件收集到 STATIC_ROOT 项目设置中定义的文件夹中。它使用以下命令调用

bash
python3 manage.py collectstatic

对于本教程,*collectstatic* 可以在应用程序上传之前运行,将应用程序中的所有静态文件复制到 STATIC_ROOT 中指定的位置。Whitenoise 然后从 STATIC_ROOT 中定义的位置(默认情况下)找到文件,并在 STATIC_URL 定义的基 URL 上提供服务。

settings.py

打开 **locallibrary/settings.py** 并将以下配置复制到文件底部。BASE_DIR 应该已经在您的文件中定义(STATIC_URL 可能在创建文件时已经定义在文件中。虽然这不会造成任何伤害,但您也可以删除重复的先前引用)。

python
# Static files (CSS, JavaScript, Images)
# https://docs.django.ac.cn/en/5.0/howto/static-files/

# The absolute path to the directory where collectstatic will collect static files for deployment.
STATIC_ROOT = BASE_DIR / 'staticfiles'

# The URL to use when referring to static files (where they will be served from)
STATIC_URL = '/static/'

我们实际上将使用名为 WhiteNoise 的库来执行文件提供服务,我们将在下一节中安装和配置它。

Whitenoise

在生产环境中提供静态文件有很多方法(我们在前几节中看到了相关的 Django 设置)。WhiteNoise 项目为直接从生产环境中的 Gunicorn 提供静态资产提供了最简单的方法之一。

查看 WhiteNoise 文档,了解它是如何工作的以及为什么这种实现是提供这些文件的相对有效方法。

设置 *WhiteNoise* 以与项目一起使用的步骤 在此处给出(并复制到下面)。

安装 whitenoise

使用以下命令在本地安装 whitenoise

bash
pip3 install whitenoise

settings.py

要将 *WhiteNoise* 安装到您的 Django 应用程序中,请打开 **locallibrary/settings.py**,找到 MIDDLEWARE 设置并将 WhiteNoiseMiddleware 添加到列表的顶部附近,就在 SecurityMiddleware 下面。

python
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

可选地,您可以减少静态文件在提供服务时的文件大小(这更有效率)。只需将以下内容添加到 **locallibrary/settings.py** 的底部。

python
# Static file serving.
# https://whitenoise.readthedocs.io/en/stable/django.html#add-compression-and-caching-support
STORAGES = {
    # ...
    "staticfiles": {
        "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
    },
}

您不需要执行任何其他操作来配置 *WhiteNoise*,因为它默认使用您的项目设置中的 STATIC_ROOTSTATIC_URL

需求

您的 Web 应用程序的 Python 需求应该存储在您的存储库根目录中的 **requirements.txt** 文件中。许多托管服务会自动安装此文件中的依赖项(在其他服务中,您必须自己执行此操作)。您可以使用命令行上的 *pip* 创建此文件(在仓库根目录中运行以下命令)。

bash
pip3 freeze > requirements.txt

在安装了上面所有不同的依赖项后,您的 **requirements.txt** 文件应该至少列出这些项目(尽管版本号可能不同)。请删除下面未列出的任何其他依赖项,除非您已明确为此应用程序添加了它们。

Django==5.0.2
dj-database-url==2.1.0
gunicorn==21.2.0
psycopg2-binary==2.9.9
wheel==0.38.1
whitenoise==6.6.0
python-dotenv==1.0.1

更新您在 GitHub 中的应用程序仓库

许多托管服务允许您从本地仓库或云端源代码控制平台导入或同步项目。这可以使部署和迭代开发变得容易得多。

您应该已经在使用 GitHub 来存储本地库源代码(这在 使用 Git 和 GitHub 进行源代码管理 中作为设置您的开发环境的一部分而设置)。

现在是备份您的“原始”项目的好时机——虽然我们在以下几节中进行的一些更改可能对在任何托管服务(或开发)中部署有用,但其他更改可能没有用。假设您已经备份了迄今为止对 GitHub 上的 main 分支所做的所有更改,您可以创建一个新分支来备份您的更改,如下所示

bash
# Fetch the latest main branch
git checkout main
git pull origin main

# Create branch vanilla_deployment from the current branch (main)
git checkout -b vanilla_deployment

# Push the new branch to GitHub
git push origin vanilla_deployment

# Switch back to main
git checkout main

# Make any further changes in a new branch
git checkout -b my_changes_for_deployment # Create a new branch

示例:在 PythonAnywhere 上托管

本节提供了在 PythonAnywhere 上托管 *LocalLibrary* 的实际演示。

为什么选择 PythonAnywhere?

我们选择使用 PythonAnywhere 是因为以下几个原因。

  • PythonAnywhere 拥有 免费的初学者计划,它是 *真正* 免费的,尽管有一些限制。它对所有开发人员来说都是负担得起的,这对 MDN 来说非常重要!

    注意:本教程已托管在 Heroku、Railway,现在是 PythonAnywhere 上,在之前免费计划停止服务后进行了迁移。我们选择 PythonAnywhere,因为我们认为该计划很可能仍然免费。我们也保留了 Railway 示例,它不是免费的,用于比较,因为它允许我们更轻松地演示诸如与在不同服务上运行的 Postgres 数据库集成之类的功能。

  • PythonAnywhere 负责基础设施,因此您无需担心。不必担心服务器、负载均衡器、反向代理等等,使入门变得容易得多。
  • 您在使用 PythonAnywhere 时学习的技能和概念是可转移的。
  • 服务和计划限制不会特别影响我们使用 PythonAnywhere 进行教程。例如
    • 初学者计划允许在 <your-username>.pythonanywhere.com 上有一个 Web 应用程序,应用程序的出站互联网访问受限,CPU/带宽低,没有 IPython/Jupyter Notebook 支持,没有免费的 Postgres 数据库。但我们的基本网站有足够的空间运行!
    • 不支持自定义域(截至撰写本文时)。
    • 环境在不使用时会关闭,因此可能难以重新启动。您可以无限期地运行它,但您需要每三个月访问一次网站并续订 Web 应用程序。
    • 有一个单独的 MySQL 数据库的免费支持,但没有 Postgres 支持。在本演示中,我们将只使用 Django 在托管的 Ubuntu 环境中创建的默认 SQLite 数据库(有足够的空间来演示库功能)。

PythonAnywhere 适用于托管本演示,如果需要可以扩展到更大的项目。您应该花时间确定它是否 适合您自己的网站

PythonAnywhere 如何运作?

PythonAnywhere 提供了一个完全基于 Web 的界面,用于上传、编辑和以其他方式处理您的应用程序。

通过界面,您可以启动一个 bash 控制台到 Ubuntu Linux 环境,您可以在其中创建您的应用程序。在本演示中,我们将使用控制台来克隆我们的本地库 GitHub 仓库,并创建一个可以在其中运行 Web 应用程序的 Python 环境。

免费计划不提供单独的 Postgres 支持。虽然我们可以使用其他一些托管服务来托管我们的数据库,但我们将只使用 Django 在托管的 Ubuntu 环境中创建的默认 SQLite 数据库(有足够的空间来演示库功能)。

应用程序运行后,可以通过 bash 控制台设置环境变量来配置应用程序以进行生产。

这是你入门所需的所有概述。

获取 PythonAnywhere 帐户

要开始使用 PythonAnywhere,您首先需要创建一个帐户。

  • 访问 PythonAnywhere 计划和定价 页面,然后选择创建初学者帐户按钮。
  • 使用您的用户名、电子邮件和密码创建一个帐户,确认条款和条件,然后选择注册
  • 然后您将登录并重定向到 PythonAnywhere 仪表板:https://www.pythonanywhere.com/user/<your_user_name>/

从 GitHub 安装库

接下来我们将打开一个 Bash 提示符,设置一个虚拟环境,并从 GitHub 获取本地库源代码。我们还将配置默认数据库并收集静态文件,以便 PythonAnywhere 可以提供服务。

  1. 首先通过选择顶部的应用程序栏中的控制台打开控制台管理屏幕。
  2. 然后选择Bash链接以创建并启动一个新控制台:PythonAnywhere 控制台管理屏幕图像请注意,您创建的任何控制台都会保存以供您以后重新使用,以及其所有历史记录。上面的绿色箭头显示此帐户有一个我们可以打开的控制台。
  3. 在控制台中,输入以下命令以创建一个名为“env_local_library”的 Python 3.10 虚拟环境,用于安装本地库依赖项。
    bash
    mkvirtualenv --python=python3.10 env_local_library
    
    这与设置 Django 开发环境中介绍的过程完全相同。我们可以将环境命名为任何名称,并且可以使用以下命令停用和重新激活它。
    bash
    deactivate
    workon env_local_library
    
  4. 接下来从 GitHub 获取库源代码。PythonAnywhere 预计您将应用程序安装到以您的网站 URL 命名的文件夹中。

    注意:因为我们使用的是免费帐户,所以您只能将帐户命名为<your_pythonaware_username>.pythonanywhere.com(例如,如果您的用户名是“Odtsetseg”,则必须将本地库源代码放入一个名为odtsetseg.pythonanywhere.com的文件夹中)。

    输入以下命令将您的库源代码克隆到一个正确命名的文件夹中(您需要将用户名值替换为自己的名称)
    bash
    git clone https://github.com/<github_username>/django-locallibrary-tutorial.git <pythonaware_username>.pythonanywhere.com
    
    # Navigate into the new folder
    cd <pythonaware_username>.pythonanywhere.com
    
  5. 使用requirements.txt文件安装库依赖项
    bash
    pip3 install -r requirements.txt
    
  6. 在托管计算机上创建和配置一个 SQLite 数据库(就像我们在开发过程中做的那样)。
    bash
    python manage.py migrate
    

    注意:对于 Railway 示例,我们将配置一个 Postgres 数据库,并通过设置DATABASE_URL环境变量连接到它。重要的是,配置要使用哪个数据库之后,要调用migrate

  7. 将所有静态文件收集到一个位置,以便可以在生产环境中提供服务
    bash
    python manage.py collectstatic --no-input
    
  8. 创建一个超级用户以访问网站(如Django 管理员网站部分所述)
    bash
    python manage.py createsuperuser
    
    请注意详细信息,因为您需要它们来测试您的网站。

设置 Web 应用程序

在获取本地库源代码并在虚拟环境中安装依赖项之后,我们需要告诉 PythonAnywhere 如何找到它们并将它们用作 Web 应用程序。

  1. 导航到网站的Web部分,然后选择添加新 Web 应用程序链接:PythonAnywhere "Web" 部分,显示用于添加新应用程序的按钮然后将打开创建新 Web 应用程序向导,指导您完成配置 Web 应用程序的主要属性。
  2. 选择下一步跳过 Web 应用程序域名配置。免费帐户将根据您的用户名创建域名:<user_name>.pythonanywhere.comPythonAnywhere 提示,用于设置新 Web 应用程序的域名
  3. 选择一个 Python Web 框架屏幕中,选择手动配置PythonAnywhere 提示,用于选择应用程序使用的 Web 框架手动配置使我们能够完全控制环境的配置方式。现在这并不重要,但如果我们要托管多个站点,可能使用不同版本的 Python 和/或 Django,则会很重要。
  4. 选择一个 Python 版本屏幕中,选择3.10PythonAnywhere 提示,用于选择 Web 应用程序的 Python 版本更一般地说,您应该选择您正在使用的 Django 版本允许的最新版本的 Python。
  5. 手动配置屏幕中,选择下一步(该屏幕只是解释了一些配置选项)PythonAnywhere 提示,解释接下来的配置选项Web 应用程序已创建,并在Web部分中显示,如所示。该屏幕有一个重新加载按钮,您可以在对配置进行任何进一步更改后使用它来重新加载 Web 应用程序。如屏幕上所述,您需要单击运行到今天起 3 个月按钮以使网站保持活动状态另外三个月(以及以后)。PythonAnywhere 配置的 Web 应用程序
  6. 向下滚动到Web选项卡的“代码”部分,然后选择指向 WSGI 配置文件的链接。这将有一个以/var/www/<user_name>_pythonanywhere_com_wsgi.py形式命名的名称。PythonAnywhere Web 选项卡中的 WSGI 文件,代码部分将文件中的内容替换为以下文本(首先使用您的用户名更新“hamishwillee”),然后选择保存按钮。
    py
    import os
    import sys
    
    path = '/home/hamishwillee/hamishwillee.pythonanywhere.com'
    if path not in sys.path:
        sys.path.append(path)
    
    os.environ['DJANGO_SETTINGS_MODULE'] = 'locallibrary.settings'
    
    from django.core.wsgi import get_wsgi_application
    application = get_wsgi_application()
    
    请注意,WSGI 文件的作用是帮助 Gunicorn 服务器找到本地库应用程序。PythonAnywhere 预计此文件位于此位置,这就是为什么项目中已经存在的 WSGI 文件不能使用的原因。
  7. 向下滚动到Web选项卡的“Virtualenv”部分。选择链接输入虚拟环境的路径(如果需要),然后输入上一节中创建的虚拟环境的路径。如果您将其命名为“env_local_library”如建议,则路径将为:/home/<user_name>/.virtualenvs/env_local_libraryPythonAnywhere Web 选项卡的 Virtualenv 部分
  8. 向下滚动到Web选项卡的“静态文件”部分。PythonAnywhere Web 选项卡的静态文件部分选择输入 URL链接,然后输入\static_files\。这是应用程序设置中的STATIC_URL,它反映了在上一节中运行collectstatic时复制文件的路径。
  9. Web选项卡的顶部附近,选择重新加载按钮以重新启动网站。然后选择网站 URL 链接以启动实时网站。

PythonAnywhere Web screen with the link to launch the site highlighted

设置 ALLOWED_HOSTS 和 CSRF_TRUSTED_ORIGINS

打开网站后,此时您将看到下面显示的错误调试屏幕。这是一个 Django 安全错误,它被引发是因为我们的源代码没有在“允许的宿主”上运行。

A detailed error page with a full traceback of an invalid HTTP_HOST header

注意:此类调试信息在您进行设置时非常有用,但在已部署的网站中存在安全风险。在下一节中,我们将向您展示如何使用环境变量在实时网站上禁用此级别的日志记录。

在您的 GitHub 项目中打开/locallibrary/settings.py,并将ALLOWED_HOSTS设置更改为包含您的 PythonAnywhere 网站 URL

python
## For example, for a site URL at 'hamishwillee.pythonanywhere.com'
## (replace the string below with your own site URL):
ALLOWED_HOSTS = ['hamishwillee.pythonanywhere.com', '127.0.0.1']

# During development, you can instead set just the base URL
# (you might decide to change the site a few times).
# ALLOWED_HOSTS = ['.pythonanywhere.com','127.0.0.1']

由于应用程序使用 CSRF 保护,因此您还需要设置CSRF_TRUSTED_ORIGINS键。打开/locallibrary/settings.py并添加类似于下面的一行

python
## For example, for a site URL is at 'web-production-3640.up.railway.app'
## (replace the string below with your own site URL):
CSRF_TRUSTED_ORIGINS = ['https://hamishwillee.pythonanywhere.com']

# During development/for this tutorial you can instead set just the base URL
# CSRF_TRUSTED_ORIGINS = ['https://*.pythonanywhere.com']

保存这些设置并将它们提交到您的 GitHub 存储库。

然后您需要更新 PythonAnywhere 上的项目版本。假设您正在使用您在文件夹<user_name>.pythonanywhere.com中的 Bash 提示符,并且您已将更改推送到主分支,那么您可以使用以下命令在 Bash 提示符中导入它们

bash
git pull origin main

使用Web选项卡上的重新启动按钮重新启动应用程序。如果您刷新托管的网站,它现在应该打开并显示网站的主页。

您应该能够使用上面创建的超级用户帐户登录,并创建作者、流派、书籍等,就像您在本地计算机上做的那样。

在 PythonAnywhere 上使用环境变量

准备发布您的网站部分中,我们修改了应用程序,使其可以使用环境变量或生产环境中.env文件中的变量进行配置。

具体来说,我们设置了库,以便您可以设置

  • DJANGO_DEBUG=False以减少在发生错误时显示给用户的调试跟踪。
  • DJANGO_SECRET_KEY在生产环境中设置为某个秘密值。
  • DATABASE_URL如果您的应用程序使用托管数据库(在本示例中我们没有使用)。

设置环境变量的方式取决于托管服务。对于 PythonAnywhere,您需要从环境文件中读取它们。我们已经为此做好了准备,因此我们所需要做的就是创建该文件。

步骤如下

  1. 打开一个 PythonAware Bash 提示符。
  2. 导航到您的应用程序目录(用您自己的帐户替换<user-name>
    bash
    cd ~/<user-name>.pythonanywhere.com
    
  3. 通过将环境变量作为键值对写入.env文件来设置它们。例如,要在 Bash 控制台中将DJANGO_DEBUG设置为False,请输入以下命令
    bash
    echo "DJANGO_DEBUG=False" >> .env
    
  4. 重新启动应用程序。

您可以尝试打开一个不存在的记录(例如,创建一个流派,然后在 URL 栏中增加数字以打开尚未创建的记录)来测试操作是否成功。如果环境变量已加载,您将收到“未找到”消息而不是详细的调试跟踪。

示例:在 Railway 上托管

本节提供了关于如何在Railway上安装LocalLibrary的实际演示。

为什么选择 Railway?

警告:Railway 不再拥有完全免费的入门层。我们保留了这些说明,因为 Railway 有一些很棒的功能,对于某些用户来说将是一个更好的选择。

Railway 由于以下几个原因成为一个有吸引力的托管选项

  • Railway 处理了大多数基础设施,因此您不必担心。不必担心服务器、负载均衡器、反向代理等,这使得入门变得容易得多。
  • Railway 专注于开发和部署的开发人员体验,这导致比许多其他替代方案更快、更平缓的学习曲线。
  • 使用 Railway 时您将学习的技能和概念是可以转移的。虽然 Railway 有一些很棒的新功能,但其他流行的托管服务使用了许多相同的理念和方法。
  • Railway 文档清晰完整。
  • 该服务似乎非常可靠,如果您最终喜欢它,定价是可预测的,而且扩展您的应用程序非常容易。

您应该花时间确定 Railway 是否适合您的网站

Railway 如何工作?

每个 Web 应用程序都在其自己的隔离且独立的虚拟化容器中运行。为了执行您的应用程序,Railway 需要能够设置适当的环境和依赖项,并了解其启动方式。对于 Django 应用程序,我们在几个文本文件中提供此信息。

  • runtime.txt:指定要使用的编程语言和版本。
  • requirements.txt:列出您的网站所需的 Python 依赖项,包括 Django。
  • Procfile:要执行以启动 Web 应用程序的进程列表。对于 Django,这通常是 Gunicorn Web 应用程序服务器(使用 .wsgi 脚本)。
  • wsgi.pyWSGI 配置,用于在 Railway 环境中调用我们的 Django 应用程序。

应用程序运行后,它可以使用 环境变量 中提供的信息进行配置。例如,使用数据库的应用程序可以使用变量 DATABASE_URL 获取地址。数据库服务本身可能由 Railway 或其他提供商托管。

开发人员通过 Railway 网站以及一个特殊的 命令行界面 (CLI) 工具与 Railway 交互。CLI 允许您将本地 GitHub 存储库与 Railway 项目关联,将本地分支中的存储库上传到实时站点,检查运行进程的日志,设置和获取配置变量等等。最有用的一项功能是,您可以使用 CLI 在与实时项目相同的环境变量下运行本地项目。

为了使我们的应用程序在 Railway 上运行,我们需要将 Django Web 应用程序放入一个 git 存储库中,添加上面的文件,与数据库附加组件集成,并进行更改以正确处理静态文件。完成所有这些操作后,我们可以设置一个 Railway 帐户,获取 Railway 客户端并安装我们的网站。

这就是您入门所需的所有概述。

更新 Railway 的应用程序

本节说明您需要对我们的 LocalLibrary 应用程序进行的更改,以使其在 Railway 上运行。我们实际上只需要创建一个 Procfileruntime.txt 文件,因为其他几乎所有内容都已经存在。

请注意,这些更改不会阻止您使用我们已经学习过的本地测试和工作流程。

Procfile

Procfile 是 Web 应用程序的“入口点”。它列出了 Railway 执行以启动您的网站的命令。

在 GitHub 存储库的根目录中创建名为 Procfile 的文件(没有文件扩展名),并将以下文本复制粘贴到其中

web: python manage.py migrate && python manage.py collectstatic --no-input && gunicorn locallibrary.wsgi

web: 前缀告诉 Railway 这是一个 Web 进程,可以发送 HTTP 流量。然后,我们调用 Django 迁移命令 python manage.py migrate 来设置数据库表。接下来,我们调用 Django 命令 python manage.py collectstatic 将静态文件收集到 STATIC_ROOT 项目设置中定义的文件夹中(参见下面的 在生产环境中提供静态文件 部分)。最后,我们启动 gunicorn 进程(一个流行的 Web 应用程序服务器),并将配置信息传递给模块 locallibrary.wsgi(使用我们的应用程序骨架创建:/locallibrary/wsgi.py)。

您会注意到我们已经设置了项目以包含 gunicorn 并支持提供静态文件!

您还可以使用 Procfile 启动工作进程或在发布部署之前运行其他非交互式任务。

运行时

runtime.txt 文件(如果已定义)会告诉 Railway 使用哪个版本的 Python。在存储库的根目录中创建该文件,并添加以下文本

python-3.10.2

注意:托管提供商并不一定支持每个 Python 运行时次要版本。它们通常会使用与您指定的版本最接近的支持版本。

重新测试并保存更改到 GitHub

在继续操作之前,请先在本地再次测试网站,并确保上述任何更改都没有破坏网站。照常运行开发 Web 服务器,然后检查网站在您的浏览器中按预期运行。

bash
python3 manage.py runserver

接下来,将更改 push 到 GitHub。在终端(导航到本地存储库后),输入以下命令

python
git checkout -b railway_changes
git add -A
git commit -m "Added files and changes required for deployment"
git push origin railway_changes

然后在 GitHub 上创建并合并 PR。

现在我们应该可以开始在 Railway 上部署 LocalLibrary 了。

获取 Railway 帐户

要开始使用 Railway,您首先需要创建一个帐户

  • 访问 railway.app,然后单击顶部工具栏中的 登录 链接。
  • 在弹出窗口中选择 GitHub,使用您的 GitHub 凭据登录
  • 然后,您可能需要访问您的电子邮件并验证您的帐户。
  • 然后您将登录到 Railway.app 仪表板:https://railway.app/dashboard

从 GitHub 在 Railway 上部署

接下来,我们将设置 Railway 以从 GitHub 部署我们的库。首先从网站顶部菜单中选择 仪表板 选项,然后选择 新建项目 按钮

Railway website dashboard with new project button

Railway 将显示新项目的选项列表,包括从首先在您的 GitHub 帐户中创建的模板部署项目,以及许多数据库。选择 从 GitHub 存储库部署

Railway website screen - deploy

将显示您在设置过程中与 Railway 共享的 GitHub 存储库中的所有项目。为本地库选择您的 GitHub 存储库:<user-name>/django-locallibrary-tutorial

Railway website screen showing a dialog to choose an existing GitHub repository or choose a new one

通过选择 立即部署 确认您的部署。

Confirmation screen - select deploy

然后,Railway 将加载并部署您的项目,并在部署选项卡中显示进度。当部署成功完成时,您将看到类似于下面的屏幕。

Railway website screen - deployment

您可以单击站点 URL(上面突出显示)在浏览器中打开站点(它仍然无法正常运行,因为设置尚未完成)。

设置 ALLOWED_HOSTS 和 CSRF_TRUSTED_ORIGINS

打开网站后,此时您将看到下面显示的错误调试屏幕。这是一个 Django 安全错误,它被引发是因为我们的源代码没有在“允许的宿主”上运行。

A detailed error page with a full traceback of an invalid HTTP_HOST header

注意:这种调试信息在您进行设置时非常有用,但在部署的站点中存在安全风险。我们将向您展示如何在站点启动并运行后禁用它。

在您的 GitHub 项目中打开 /locallibrary/settings.py,并将 ALLOWED_HOSTS 设置更改为包括您的 Railway 站点 URL

python
## For example, for a site URL at 'web-production-3640.up.railway.app'
## (replace the string below with your own site URL):
ALLOWED_HOSTS = ['web-production-3640.up.railway.app', '127.0.0.1']

# During development, you can instead set just the base URL
# (you might decide to change the site a few times).
# ALLOWED_HOSTS = ['.railway.com','127.0.0.1']

由于应用程序使用 CSRF 保护,因此您还需要设置CSRF_TRUSTED_ORIGINS键。打开/locallibrary/settings.py并添加类似于下面的一行

python
## For example, for a site URL is at 'web-production-3640.up.railway.app'
## (replace the string below with your own site URL):
CSRF_TRUSTED_ORIGINS = ['https://web-production-3640.up.railway.app']

# During development/for this tutorial you can instead set just the base URL
# CSRF_TRUSTED_ORIGINS = ['https://*.railway.app']

然后保存您的设置并将它们提交到您的 GitHub 存储库(Railway 将自动更新并重新部署您的应用程序)。

预配并连接 PostgreSQL 数据库

接下来,我们需要创建一个 PostgreSQL 数据库并将其连接到我们刚刚部署的 Django 应用程序。(如果您现在打开站点,您将收到一个新的错误,因为无法访问数据库)。我们将作为应用程序项目的一部分创建数据库,尽管您可以在单独的项目中创建数据库。

在 Railway 上,从网站顶部菜单中选择 仪表板 选项,然后选择您的应用程序项目。在此阶段,它只包含您应用程序的单个服务(可以选择它来设置服务的变量和其他详细信息)。设置按钮可用于更改项目范围的设置。选择 新建 按钮,用于将服务添加到项目中。

Railway project with new service button highlighted

当系统提示您有关要添加的服务类型时,请选择 数据库

Railway project - select database as new service

然后选择 添加 PostgreSQL 开始添加数据库

Railway project - select Postgres as new service

然后,Railway 将在同一个项目中预配包含一个空数据库的服务。完成后,您将在项目视图中看到应用程序和数据库服务。

Railway project with application and Postgres database service

选择 Web 服务,然后选择 变量 选项卡。选择 新建变量,然后在 变量名称 框中,选择 添加引用。向下滚动并选择 DATABASE_URL(这是我们设置 locallibrary 以读取为环境变量的变量的名称)。

Railway website screen selecting a DATABASE_URL

然后选择 添加 添加变量引用,最后选择 部署(这将出现在一个弹出窗口中)。请注意,您也可以打开 PostgreSQL 数据库,然后打开其变量选项卡,并将变量复制过来。

如果您现在打开项目,它应该与本地显示的完全相同。但是请注意,目前无法使用数据填充库,因为我们还没有创建超级用户帐户。我们将使用本地计算机上的 CLI 工具来执行此操作。

安装客户端

按照 此处说明 下载并安装适用于您本地操作系统的 Railway 客户端。

安装客户端后,您将能够运行命令。一些更重要的操作包括将计算机的当前目录部署到关联的 Railway 项目(无需上传到 GitHub),以及使用与生产服务器上相同的设置在本地运行 Django 项目。我们在下一节中将介绍这些操作。

您可以通过在终端中输入以下内容来获取所有可能命令的列表。

bash
railway help

注意:在以下部分中,我们使用 railway loginrailway link 将当前项目链接到一个目录。如果您被系统注销,则需要再次调用这两个命令才能重新链接项目。

配置超级用户

为了创建超级用户,我们需要对生产数据库调用 Django createsuperuser 命令(这与我们在 Django 教程第 4 部分:Django 管理员站点 > 创建超级用户 中本地运行的操作相同)。Railway 不提供对服务器的直接终端访问,我们无法将此命令添加到 Procfile 中,因为它具有交互性。

我们可以做的是,当 Django 项目连接到 生产 数据库时,在本地调用此命令。Railway 客户端通过提供一种机制来在使用与生产服务器相同的环境变量(包括数据库连接字符串)的情况下在本地运行命令,使这一操作变得容易。

首先在 locallibrary 项目的 git 克隆中打开一个终端或命令提示符。然后使用 loginlogin --browserless 命令登录到您的浏览器帐户(按照客户端或网站的任何后续提示和说明完成登录)

bash
railway login

登录后,使用以下命令将您当前的 locallibrary 目录链接到关联的 Railway 项目。请注意,您需要在系统提示时选择/输入一个特定的项目

bash
railway link

现在本地目录和项目已 链接,您可以使用生产环境中的设置运行本地 Django 项目。首先确保您的正常 Django 开发环境 已准备就绪。然后调用以下命令,根据需要输入名称、电子邮件和密码

bash
railway run python manage.py createsuperuser

现在,您应该能够打开您的网站管理员区域(https://[your-url].railway.app/admin/)并填充数据库,就像在 Django 教程第 4 部分:Django 管理员站点 中所示。

设置配置变量

最后一步是使站点安全。具体来说,我们需要禁用调试日志记录并设置一个秘密 CSRF 密钥。在 准备网站发布 中完成了从环境变量读取所需值的步骤(参见 DJANGO_DEBUGDJANGO_SECRET_KEY)。

打开项目的详细信息屏幕,然后选择 变量 选项卡。这应该已经包含 DATABASE_URL,如下所示。

Railway - add a new variable screen

生成加密密钥的方法有很多。一个简单的方法是在您的开发计算机上运行以下 Python 命令

bash
python -c "import secrets; print(secrets.token_urlsafe())"

选择**新建变量**按钮,并输入密钥 `DJANGO_SECRET_KEY` 和您的密钥值(然后选择**添加**)。然后输入密钥 `DJANGO_DEBUG` 和值 `False`。最终的变量集应如下所示

Railway screen showing all the project variables

调试

Railway 客户端提供 `logs` 命令来显示日志的尾部(每个项目的完整日志都可以在网站上找到)

bash
railway logs

如果您需要更多信息,则需要查看 Django 日志

总结

在本教程中,我们将介绍如何在生产环境中设置 Django 应用程序,以及关于使用 Django 的一系列教程。我们希望您发现它们有用。您可以查看 GitHub 上的完整源代码

下一步是阅读我们最后几篇文章,然后完成评估任务。

另请参阅