为 Django 贡献你的第一个代码

介绍

有兴趣回馈社区一点吗?也许你发现了 Django 中的一个 bug,希望它能被修复,或者你想要添加一个小功能。

回馈 Django 本身是解决你自身问题的最佳方式。这起初看起来可能令人生畏,但这是一条有着完善文档、工具和社区支持的成熟路径。我们将引导你完成整个过程,以便你能通过示例学习。

本教程面向谁?

另请参阅

如果你正在寻找有关代码贡献细节的参考,请参阅贡献代码文档。

对于本教程,我们假设你至少对 Django 的工作原理有基本了解。这意味着你应该能够轻松完成关于编写你的第一个 Django 应用的现有教程。此外,你应该对 Python 本身有很好的理解。但如果你没有,Dive Into Python 是一本很棒的(而且免费的)在线书籍,适合 Python 初学者。

那些不熟悉版本控制系统和 Trac 的人会发现本教程及其链接包含足够的信息来入门。但是,如果你计划定期为 Django 贡献代码,你可能需要阅读更多关于这些不同工具的信息。

不过,在大多数情况下,本教程尝试尽可能多地解释,以便能够为最广泛的受众提供帮助。

在哪里寻求帮助

如果你在学习本教程时遇到问题,请在Django 论坛django-developers上发帖,或访问#django-dev on irc.libera.chat 与其他可能能够提供帮助的 Django 用户聊天。

本教程涵盖哪些内容?

我们将引导你完成第一次为 Django 贡献代码的过程。在本教程结束时,你应该对所涉及的工具和流程有基本的了解。具体来说,我们将涵盖以下内容:

  • 安装 Git。

  • 下载 Django 的开发版本副本。

  • 运行 Django 的测试套件。

  • 为你的更改编写测试。

  • 编写你的更改的代码。

  • 测试你的更改。

  • 提交拉取请求。

  • 在哪里查找更多信息。

完成本教程后,你可以查看其余的Django 的贡献文档。它包含大量有用的信息,对于任何希望成为 Django 常规贡献者的人来说都是必读的。如果你有疑问,它可能已经包含了答案。

需要 Python 3!

当前版本的 Django 不支持 Python 2.7。请从Python 的下载页面或使用你的操作系统的包管理器获取 Python 3。

对于 Windows 用户

请参阅安装 Python Windows 文档以获取更多指导。

行为准则

作为贡献者,你可以帮助我们保持 Django 社区的开放和包容。请阅读并遵守我们的行为准则

安装 Git

在本教程中,你需要安装 Git 来下载 Django 的当前开发版本并为你的更改生成一个分支。

要检查你是否已安装 Git,请在命令行中输入git。如果你收到提示说找不到此命令的消息,则必须下载并安装它,请参阅Git 的下载页面

如果你不太熟悉 Git,你可以在命令行中输入git help 来了解它的命令(安装后)。

获取 Django 开发版本的副本

为 Django 贡献代码的第一步是获取源代码副本。首先,在 GitHub 上 fork Django。然后,在命令行中,使用cd命令导航到要存放 Django 本地副本的目录。

使用以下命令下载 Django 源代码库:

$ git clone https://github.com/YourGitHubName/django.git
...\> git clone https://github.com/YourGitHubName/django.git

低带宽连接?

你可以将--depth 1参数添加到git clone以跳过下载所有 Django 的提交历史记录,这会将数据传输量从约 250 MB 减少到约 70 MB。

现在你有了 Django 的本地副本,你可以像使用pip安装任何包一样安装它。最方便的方法是使用*虚拟环境*,这是 Python 中内置的一个功能,它允许你为每个项目保留一个单独的已安装包目录,以防止它们相互干扰。

最好将所有虚拟环境都放在一个地方,例如放在主目录中的.virtualenvs/

通过运行以下命令创建一个新的虚拟环境:

$ python3 -m venv ~/.virtualenvs/djangodev
...\> py -m venv %HOMEPATH%\.virtualenvs\djangodev

路径是新的环境将在你的计算机上保存的位置。

设置虚拟环境的最后一步是激活它:

$ source ~/.virtualenvs/djangodev/bin/activate

如果source命令不可用,你可以尝试使用点代替:

$ . ~/.virtualenvs/djangodev/bin/activate

每次打开新的终端窗口时,都必须激活虚拟环境。

对于 Windows 用户

要在 Windows 上激活虚拟环境,请运行:

...\> %HOMEPATH%\.virtualenvs\djangodev\Scripts\activate.bat

当前激活的虚拟环境的名称显示在命令行上,以帮助你跟踪正在使用的虚拟环境。在此名称显示时,通过pip安装的任何内容都将安装在该虚拟环境中,与其他环境和系统范围的包隔离。

继续安装先前克隆的 Django 副本:

$ python -m pip install -e /path/to/your/local/clone/django/
...\> py -m pip install -e \path\to\your\local\clone\django\

已安装的 Django 版本现在通过以可编辑模式安装指向你的本地副本。你将立即看到对它的任何更改,这在编写你的第一个贡献时非常有帮助。

使用 Django 的本地副本创建项目

使用 Django 项目测试你的本地更改可能会有所帮助。首先,你必须创建一个新的虚拟环境,以可编辑模式安装先前克隆的 Django 本地副本,并在你的 Django 本地副本之外创建一个新的 Django 项目。你将立即在你的新项目中看到对 Django 的任何更改,这在编写你的第一个贡献时非常有帮助,尤其是在测试对 UI 的任何更改时。

你可以按照教程中的说明创建 Django 项目。

第一次运行 Django 的测试套件

在为 Django 贡献代码时,非常重要的是你的代码更改不会将 bug 引入 Django 的其他区域。检查在进行更改后 Django 是否仍然有效的一种方法是运行 Django 的测试套件。如果所有测试都仍然通过,那么你可以合理地确定你的更改有效并且没有破坏 Django 的其他部分。如果你以前从未运行过 Django 的测试套件,最好先运行一次以熟悉其输出。

在运行测试套件之前,使用cd tests命令进入 Django 的tests/目录,并通过运行以下命令安装测试依赖项:

$ python -m pip install -r requirements/py3.txt
...\> py -m pip install -r requirements\py3.txt

如果在安装过程中遇到错误,你的系统可能缺少一个或多个 Python 包的依赖项。请参阅失败的包的文档或使用遇到的错误消息在网上搜索。

现在我们可以运行测试套件了:

$ ./runtests.py
...\> runtests.py 

现在坐下来放松一下。Django 的整个测试套件包含数千个测试,运行至少需要几分钟,具体取决于你的计算机速度。

在 Django 的测试套件运行期间,你将看到一系列字符,表示每个测试完成时的状态。E表示在测试期间引发了错误,F表示测试的断言失败。这两者都被认为是测试失败。同时,xs分别表示预期的失败和跳过的测试。点表示通过的测试。

跳过的测试通常是由于缺少运行测试所需的外部库;请参阅运行所有测试以获取依赖项列表,并确保安装与你正在进行的更改相关的任何测试(在本教程中我们不需要任何测试)。某些测试特定于特定的数据库后端,如果未使用该后端进行测试,则将被跳过。SQLite 是默认设置的数据库后端。要使用不同的后端运行测试,请参阅使用另一个设置模块

测试完成后,你会看到一条消息,告知你测试套件是通过还是失败。由于你尚未对 Django 的代码进行任何更改,因此整个测试套件**应该**通过。如果出现失败或错误,请确保你已正确执行所有之前的步骤。更多信息,请参见 运行单元测试

请注意,最新的 Django “main” 分支可能并不总是稳定的。在针对“main”分支进行开发时,你可以查看 Django 的持续集成构建,以确定失败是特定于你的机器还是也存在于 Django 的官方构建中。如果你点击查看特定构建,你可以查看“配置矩阵”,其中显示了按 Python 版本和数据库后端细分的失败。

注意

对于本教程和我们正在处理的工单,针对 SQLite 进行测试就足够了,但是,可以使用 不同的数据库运行测试(有时是必要的)。进行 UI 更改时,需要 运行 Selenium 测试

处理特性

在本教程中,我们将使用一个“虚构工单”作为案例研究。以下是虚构的详细信息:

工单 #99999 – 允许制作吐司

Django 应该提供一个函数 django.shortcuts.make_toast(),该函数返回 'toast'

我们现在将实现此功能及其相关的测试。

创建分支

在进行任何更改之前,请为该工单创建一个新分支。

$ git checkout -b ticket_99999
...\> git checkout -b ticket_99999

你可以为分支选择任何你想要的名称,“ticket_99999”只是一个示例。在此分支中进行的所有更改都将特定于该工单,并且不会影响我们之前克隆的代码主副本。

为你的工单编写一些测试

在大多数情况下,要将贡献纳入 Django,必须包含测试。对于错误修复贡献,这意味着编写回归测试以确保该错误不会在以后被重新引入 Django。回归测试的编写方式应使其在错误仍然存在时失败,并在错误修复后通过。对于包含新功能的贡献,你需要包含测试,以确保新功能正常工作。它们也应该在新功能不存在时失败,并在实现后通过。

一个好方法是在进行任何代码更改之前先编写新的测试。这种开发风格称为 测试驱动开发,可以应用于整个项目和单个更改。编写测试后,运行它们以确保它们确实失败(因为你尚未修复该错误或添加该功能)。如果你的新测试没有失败,则需要修复它们以使其失败。毕竟,无论是否存在错误都通过的回归测试对于防止该错误将来再次出现并没有多大帮助。

现在是我们的实践示例。

为工单 #99999 编写测试

为了解决此工单,我们将向 django.shortcuts 模块添加一个 make_toast() 函数。首先,我们将编写一个尝试使用该函数并检查其输出是否正确的测试。

导航到 Django 的 tests/shortcuts/ 文件夹并创建一个新文件 test_make_toast.py。添加以下代码:

from django.shortcuts import make_toast
from django.test import SimpleTestCase


class MakeToastTests(SimpleTestCase):
    def test_make_toast(self):
        self.assertEqual(make_toast(), "toast")

此测试检查 make_toast() 是否返回 'toast'

但是,这个测试看起来有点难……

如果你以前从未处理过测试,乍一看它们可能看起来有点难写。幸运的是,测试在计算机编程中是一个非常大的课题,因此有很多相关信息。

运行你的新测试

由于我们尚未对 django.shortcuts 进行任何修改,因此我们的测试应该失败。让我们运行 shortcuts 文件夹中的所有测试,以确保确实如此。使用 cd 命令进入 Django 的 tests/ 目录并运行:

$ ./runtests.py shortcuts
...\> runtests.py shortcuts

如果测试正确运行,你应该会看到一个与我们添加的测试方法相对应的失败,并出现此错误:

ImportError: cannot import name 'make_toast' from 'django.shortcuts'

如果所有测试都通过了,那么你需要确保你已将上面显示的新测试添加到适当的文件夹和文件名中。

编写你的工单代码

接下来,我们将添加 make_toast() 函数。

导航到 django/ 文件夹并打开 shortcuts.py 文件。在底部添加:

def make_toast():
    return "toast"

现在我们需要确保我们之前编写的测试通过,这样我们就可以查看我们添加的代码是否正常工作。再次,导航到 Django 的 tests/ 目录并运行:

$ ./runtests.py shortcuts
...\> runtests.py shortcuts

所有测试都应该通过。如果没有,请确保你已将函数正确添加到正确文件中。

第二次运行 Django 的测试套件

验证你的更改和测试正常工作后,最好运行整个 Django 测试套件,以验证你的更改是否未向 Django 的其他区域引入任何错误。虽然成功通过整个测试套件并不能保证你的代码没有错误,但它确实有助于识别许多否则可能被忽略的错误和回归。

要运行整个 Django 测试套件,请使用 cd 命令进入 Django 的 tests/ 目录并运行:

$ ./runtests.py
...\> runtests.py 

编写文档

这是一个新功能,因此应对其进行记录。打开文件 docs/topics/http/shortcuts.txt 并将以下内容添加到文件的末尾:

``make_toast()``
================

.. function:: make_toast()

.. versionadded:: 2.2

Returns ``'toast'``.

由于此新功能将在即将发布的版本中提供,因此它还会添加到 Django 下一个版本的发布说明中。打开 docs/releases/ 中最新版本的发布说明(撰写本文时为 2.2.txt)。在“次要功能”标题下添加注释:

:mod:`django.shortcuts`
~~~~~~~~~~~~~~~~~~~~~~~

* The new :func:`django.shortcuts.make_toast` function returns ``'toast'``.

有关编写文档的更多信息,包括对 versionadded 部分的解释,请参见 编写文档。该页面还解释了如何在本地构建文档副本,以便你可以预览将生成的 HTML。

预览你的更改

现在是时候查看分支中所做的更改了。要准备所有更改以进行提交,请运行:

$ git add --all
...\> git add --all

然后显示 Django 的当前副本(包含你的更改)与你在本教程前面签出的修订版之间的差异:

$ git diff --cached
...\> git diff --cached

使用箭头键上下移动。

diff --git a/django/shortcuts.py b/django/shortcuts.py
index 7ab1df0e9d..8dde9e28d9 100644
--- a/django/shortcuts.py
+++ b/django/shortcuts.py
@@ -156,3 +156,7 @@ def resolve_url(to, *args, **kwargs):

     # Finally, fall back and assume it's a URL
     return to
+
+
+def make_toast():
+    return 'toast'
diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt
index 7d85d30c4a..81518187b3 100644
--- a/docs/releases/2.2.txt
+++ b/docs/releases/2.2.txt
@@ -40,6 +40,11 @@ database constraints. Constraints are added to models using the
 Minor features
 --------------

+:mod:`django.shortcuts`
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* The new :func:`django.shortcuts.make_toast` function returns ``'toast'``.
+
 :mod:`django.contrib.admin`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~

diff --git a/docs/topics/http/shortcuts.txt b/docs/topics/http/shortcuts.txt
index 7b3a3a2c00..711bf6bb6d 100644
--- a/docs/topics/http/shortcuts.txt
+++ b/docs/topics/http/shortcuts.txt
@@ -271,3 +271,12 @@ This example is equivalent to::
         my_objects = list(MyModel.objects.filter(published=True))
         if not my_objects:
             raise Http404("No MyModel matches the given query.")
+
+``make_toast()``
+================
+
+.. function:: make_toast()
+
+.. versionadded:: 2.2
+
+Returns ``'toast'``.
diff --git a/tests/shortcuts/test_make_toast.py b/tests/shortcuts/test_make_toast.py
new file mode 100644
index 0000000000..6f4c627b6e
--- /dev/null
+++ b/tests/shortcuts/test_make_toast.py
@@ -0,0 +1,7 @@
+from django.shortcuts import make_toast
+from django.test import SimpleTestCase
+
+
+class MakeToastTests(SimpleTestCase):
+    def test_make_toast(self):
+        self.assertEqual(make_toast(), 'toast')

预览更改完成后,按 q 键返回命令行。如果差异看起来没问题,则可以提交更改。

提交更改

要提交更改:

$ git commit
...\> git commit

这将打开一个文本编辑器以键入提交消息。遵循 提交消息指南 并编写类似这样的消息:

Fixed #99999 -- Added a shortcut function to make toast.

推送提交并创建拉取请求

提交更改后,将其发送到你在 GitHub 上的分支(如果你的分支名称不同,请将“ticket_99999”替换为你分支的名称):

$ git push origin ticket_99999
...\> git push origin ticket_99999

你可以通过访问 Django GitHub 页面 来创建拉取请求。你将在“你最近推送的分支”下看到你的分支。点击它旁边的“比较和拉取请求”。

请不要在本教程中执行此操作,但在显示更改预览的下一页上,你将点击“创建拉取请求”。

后续步骤

恭喜你,你已经学习了如何向 Django 发起拉取请求!你可能需要的更高级技术的详细信息在 使用 Git 和 GitHub 中。

现在,你可以利用这些技能来帮助改进 Django 的代码库。

新贡献者的更多信息

在深入参与 Django 的贡献之前,还有一些关于贡献的更多信息你可能应该查看一下:

  • 你应该阅读 Django 关于 认领工单和提交拉取请求 的文档。它涵盖了 Trac 礼仪、如何认领工单、预期的编码风格(代码和文档)、以及许多其他重要细节。

  • 首次贡献者还应该阅读 Django 的 首次贡献者文档。它为我们这些刚开始帮助 Django 的人提供了很多好的建议。

  • 阅读完这些内容后,如果你仍然想了解更多关于贡献的信息,你可以随时浏览 Django 关于贡献的文档 的其余部分。它包含大量有用的信息,应该是你解答任何问题的首选资源。

寻找你的第一个真正的问题

浏览完一些信息后,你就可以开始寻找你自己的问题来贡献了。请特别注意带有“简单易上手”标准的问题。这些问题通常比较简单,非常适合首次贡献者。一旦你熟悉了对 Django 的贡献,你就可以开始处理更困难和复杂的问题。

如果你只想马上开始(没有人会责怪你!),可以尝试查看没有分支的简单问题需要改进的分支的简单问题列表。如果你熟悉编写测试,你还可以查看需要测试的简单问题列表。请记住遵循关于认领问题的指南,这些指南在 Django 关于认领问题和提交分支的文档链接中提到。

创建拉取请求后接下来做什么?

问题有了分支后,需要其他人审查。提交拉取请求后,更新问题的元数据,将问题的标志设置为“已打补丁”、“不需要测试”等,以便其他人可以找到它进行审查。贡献并不一定总是意味着从头编写代码。审查开放的拉取请求也是非常有帮助的贡献。详情请参阅问题分类

返回顶部