为 Django 编写第一个补丁 — Django 文档
编写你的第一个 Django 补丁
介绍
有兴趣回馈社区吗? 也许您在 Django 中发现了一个您希望修复的错误,或者您想要添加一个小功能。
回馈 Django 本身是解决您自己的问题的最佳方式。 乍一看,这可能令人生畏,但实际上非常简单。 我们将引导您完成整个过程,以便您可以通过示例进行学习。
这个教程是给谁看的?
对于本教程,我们希望您至少对 Django 的工作原理有基本的了解。 这意味着您应该可以轻松浏览有关 编写第一个 Django 应用程序 的现有教程。 此外,您应该对 Python 本身有很好的了解。 但如果你不这样做,深入 Python 是一本非常棒的(免费的)在线书籍,适合 Python 初学者。
那些不熟悉版本控制系统和 Trac 的人会发现本教程及其链接包含的信息刚好足以开始使用。 但是,如果您计划定期为 Django 做出贡献,您可能需要阅读更多有关这些不同工具的信息。
当然对于此教程中的大部分内容,Django 会尽可能做出解释以帮助广大的读者。
从哪里获得帮助:
如果您在阅读本教程时遇到问题,请向 django-developers 发送消息或访问 irc.libera.chat 上的 #django-dev 与其他 Django 用户聊天谁能帮忙。
这个指南涵盖哪些内容?
我们将引导您第一次向 Django 贡献补丁。 在本教程结束时,您应该对所涉及的工具和流程有基本的了解。 具体来说,我们将涵盖以下内容:
- 安装 Git。
- 下载 Django 开发版本的副本。
- 运行 Django 的测试套件。
- 为你的补丁写一个测试。
- 为你的补丁编写代码。
- 测试你的补丁。
- 提交一个 pull request(PR)。
- 在哪里查找更多的信息。
完成本教程后,您可以查看 Django 中关于贡献 的文档的其余部分。 它包含许多重要信息,是任何想成为 Django 定期贡献者的人的必读之物。 如果你有问题,它可能有答案。
对于 Windows 用户
在 Windows 上安装 Python 时,请确保选中“将 python.exe 添加到路径”选项,以便它始终在命令行上可用。
安装 Git
对于本教程,您需要安装 Git 来下载 Django 的当前开发版本并为您所做的更改生成补丁文件。
要检查您是否安装了 Git,请在命令行中输入 git
。 如果您收到消息说找不到此命令,则必须下载并安装它,请参阅 Git 的下载页面 。
如果您不太熟悉 Git,您总是可以通过在命令行中输入 git help
来了解有关其命令的更多信息(安装后)。
获取 Django 开发版本的副本
为 Django 做出贡献的第一步是获取源代码的副本。 首先, 在 GitHub 上 fork Django。 然后,从命令行,使用 cd
命令导航到您希望 Django 的本地副本所在的目录。
使用下面的命令来下载 Django 的源码库:
低速宽带连接?
您可以将 --depth 1
参数添加到 git clone
以跳过下载所有 Django 的提交历史记录,从而将数据传输从 ~250 MB 减少到 ~70 MB。
现在您有了 Django 的本地副本,您可以像使用 pip
安装任何软件包一样安装它。 最方便的方法是使用 虚拟环境 ,这是 Python 内置的一项功能,允许您为每个项目保留一个单独的已安装包目录,以便它们不会干扰彼此。
将所有虚拟环境保存在一个地方是一个好主意,例如在您的主目录中的 .virtualenvs/
中。
通过运行以下命令创建一个虚拟环境:
该路径就是保存这个新的虚拟运行环境的地方。
设置虚拟环境的最后一步是激活它:
$ source ~/.virtualenvs/djangodev/bin/activate
如果 source
命令不可用,您可以尝试使用点代替:
$ . ~/.virtualenvs/djangodev/bin/activate
对于 Windows 用户
在 Windows 下采用如下命令进行激活虚拟环境:
...\> %HOMEPATH%\.virtualenvs\djangodev\Scripts\activate.bat
每当您打开新的终端窗口时,您都必须激活虚拟环境。 virtualenvwrapper 是一个有用的工具,可以让这更方便。
当前激活的虚拟环境的名称显示在命令行上,以帮助您跟踪正在使用的虚拟环境。 在显示此名称时通过 pip
安装的任何内容都将安装在该虚拟环境中,与其他环境和系统范围的软件包隔离。
下一步安装之前克隆的 Django 副本:
通过以可编辑模式安装,已安装的 Django 版本现在指向您的本地副本。 您将立即看到对其所做的任何更改,这在编写第一个补丁时非常有帮助。
使用 Django 本地副本创建项目
使用 Django 项目测试您的本地更改可能会有所帮助。 首先,您必须创建一个新的虚拟环境, 以可编辑模式 安装先前克隆的 Django 本地副本,并在您的 Django 本地副本之外创建一个新的 Django 项目。 您将立即在新项目中看到对 Django 所做的任何更改,这在编写第一个补丁时很有帮助。
第一次运行 Django 的测试套件
在为 Django 做出贡献时,重要的是您的代码更改不会将错误引入 Django 的其他领域。 在您进行更改后检查 Django 是否仍然有效的一种方法是运行 Django 的测试套件。 如果所有测试仍然通过,那么您可以合理地确定您的更改有效并且没有破坏 Django 的其他部分。 如果您以前从未运行过 Django 的测试套件,最好事先运行一次以熟悉其输出。
在运行测试套件之前,通过 cd
-ing 将其依赖项安装到 Django tests/
目录中,然后运行:
如果您在安装过程中遇到错误,您的系统可能缺少一个或多个 Python 包的依赖项。 查阅失败包的文档或使用您遇到的错误消息在 Web 上搜索。
现在我们准备运行测试套件。 如果您使用的是 GNU/Linux、macOS 或其他一些 Unix 版本,请运行:
现在坐下来放松一下。 Django 的整个测试套件有数千个测试,运行至少需要几分钟,具体取决于您的计算机速度。
当 Django 的测试套件运行时,您会看到一个字符流,代表每个测试完成时的状态。 E
表示测试期间出现错误,F
表示测试断言失败。 这两个都被认为是测试失败。 同时,x
和 s
分别表示预期失败和跳过测试。 点表示通过测试。
跳过测试通常是由于缺少运行测试所需的外部库; 请参阅 运行所有测试 以获取依赖项列表,并确保为与您所做更改相关的测试安装任何测试(本教程不需要任何测试)。 某些测试特定于特定的数据库后端,如果不使用该后端进行测试,将被跳过。 SQLite 是默认设置的数据库后端。 要使用不同的后端运行测试,请参阅 使用另一个设置模块 。
测试完成后,您应该会收到一条消息,通知您测试套件是通过还是失败。 由于您尚未对 Django 的代码进行任何更改,因此整个测试套件 应该 通过。 如果您遇到失败或错误,请确保您已正确执行所有前面的步骤。 有关更多信息,请参阅 运行单元测试 。
请注意,最新的 Django master 可能并不总是稳定的。 在针对 master 开发时,您可以检查 Django 的持续集成构建 以确定故障是否特定于您的机器,或者它们是否也存在于 Django 的官方构建中。 如果单击查看特定构建,则可以查看“配置矩阵”,其中显示了按 Python 版本和数据库后端细分的故障。
尝试搞定一项新功能
在本教程中,我们将使用“假票”作为案例研究。 以下是想象中的细节:
票号 #99999 – 允许烤面包
Django 应该提供一个返回 'toast'
的函数 django.shortcuts.make_toast()
。
我们现在将实现此功能和相关测试。
为你的补丁创建一个分支
在做出任何修改之前,为你的工单创建一个分支:
您可以为分支选择任何您想要的名称,例如“ticket_99999”。 在此分支中所做的所有更改都将特定于票证,不会影响我们之前克隆的代码的主副本。
为你的工单写一些测试用例
在大多数情况下,要让 Django 接受补丁,它必须包含测试。 对于错误修复补丁,这意味着编写回归测试以确保该错误以后永远不会重新引入 Django。 回归测试应该以这样的方式编写,即在错误仍然存在时它会失败并在错误被修复后通过。 对于包含新功能的补丁,您需要包括确保新功能正常工作的测试。 当新功能不存在时,它们也应该失败,然后在实现后通过。
这样做的一个好方法是先编写新测试,然后再对代码进行任何更改。 这种开发风格称为测试驱动开发,可以应用于整个项目和单个补丁。 编写测试后,然后运行它们以确保它们确实失败(因为您尚未修复该错误或添加该功能)。 如果您的新测试没有失败,您将需要修复它们以便它们成功。 毕竟,无论是否存在错误都通过的回归测试对于防止该错误再次发生并没有多大帮助。
现在看我们的操作示例。
为工单 #99999 写测试
为了解决这个问题,我们将在顶层 django
模块中添加一个 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/
目录并运行:
如果测试运行正确,您应该会看到一个与我们添加的测试方法相对应的失败,并显示以下错误:
ImportError: cannot import name 'make_toast' from 'django.shortcuts'
如果所有测试都通过了,那么您需要确保将上面显示的新测试添加到适当的文件夹和文件名中。
为你的工单编写代码
接下来我们将添加 make_toast()
函数。
导航到 django/
文件夹并打开 shortcuts.py
文件。 在底部添加:
def make_toast():
return 'toast'
现在我们需要确保我们之前编写的测试通过,以便我们可以查看我们添加的代码是否正常工作。 再次导航到 Django tests/
目录并运行:
一切都应该过去。 如果没有,请确保您将函数正确添加到正确的文件中。
第二次运行 Django 的测试套件
一旦您确认您的补丁和您的测试工作正常,运行整个 Django 测试套件只是为了验证您的更改没有将任何错误引入 Django 的其他区域是一个好主意。 虽然成功通过整个测试套件并不能保证您的代码没有错误,但它确实有助于识别许多否则可能会被忽视的错误和回归。
要运行整个 Django 测试套件,cd
进入 Django tests/
目录并运行:
书写文档
这是一个新功能,所以应该记录下来。 打开文件 docs/topics/http/shortcuts.txt
并在文件末尾添加以下内容:
``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。
预览你的修改
现在是时候检查我们的补丁中所做的所有更改了。 要暂存准备提交的所有更改,请运行:
然后将你当前版本(包含有你修改的内容)的拷贝和你最初在教程中取出的版本对比:
使用方向键上下移动
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
键返回命令行。 如果补丁的内容看起来没问题,就该提交更改了。
提交补丁中的修改
为了提交这些修改:
这将打开一个文本编辑器来输入提交消息。 遵循 提交消息指南 并编写如下消息:
Fixed #99999 -- Added a shortcut function to make toast.
推送这次提交并生成一个 pull 请求
提交补丁后,将其发送到您在 GitHub 上的分支(如果不同,请将“ticket_99999”替换为您的分支名称):
您可以通过访问 Django GitHub 页面 创建拉取请求。 您将在“您最近推送的分支”下看到您的分支。 单击旁边的“比较和拉取请求”。
请不要在本教程中执行此操作,但在显示补丁预览的下一页上,您将单击“创建拉取请求”。
下一步
恭喜,您已经学会了如何向 Django 发出拉取请求! 您可能需要的更高级技术的详细信息在 使用 Git 和 GitHub 中。
现在,您可以通过帮助改进 Django 的代码库来充分利用这些技能。
针对新贡献者的更多注意事项
在您开始为 Django 编写补丁之前,您可能应该查看更多有关贡献的信息:
- 您应该确保阅读关于 申领门票和提交补丁 的 Django 文档。 它涵盖了 Trac 礼仪、如何为自己索取票证、补丁的预期编码风格以及许多其他重要细节。
- 首次贡献者还应阅读 Django 的 首次贡献者 文档。 它为我们这些刚开始帮助 Django 的人提供了很多很好的建议。
- 在这些之后,如果您仍然渴望获得更多关于贡献的信息,您可以随时浏览 Django 关于贡献 的文档的其余部分。 它包含大量有用的信息,应该是您回答任何问题的第一个来源。
寻找你的第一个真正意义上的工单
一旦您浏览了其中的一些信息,您就可以准备出去寻找一张属于您自己的票来为其编写补丁。 特别注意具有“容易挑选”标准的门票。 这些票在本质上通常要简单得多,非常适合第一次投稿的人。 一旦您熟悉了为 Django 做贡献,您就可以继续为更困难和更复杂的票证编写补丁。
如果您只是想开始(没有人会责怪您!),请尝试查看需要补丁的 easy 票证列表 和需要改进的补丁的 easy 票证列表[ X209X]。 如果你熟悉编写测试,你还可以查看需要测试的简单票据列表。 请记住遵循有关 申领门票和提交补丁 的 Django 文档链接中提到的申领门票指南。
创建拉取请求后下一步是什么?
一张票打上补丁后,需要经过第二组眼睛的审核。 提交拉取请求后,通过在票证上设置标志来更新票证元数据,例如“有补丁”、“不需要测试”等,以便其他人可以找到它进行审查。 贡献并不总是意味着从头开始编写补丁。 查看现有补丁也是一个非常有用的贡献。 有关详细信息,请参阅 分类票证 。