为Django编写第一个补丁

介绍

有兴趣回馈社会一点吗?也许你在Django发现了一个你希望看到修复的bug,或者你想要添加一个小特性。

回馈Django本身是解决您自己的问题的最好方法。乍一看,这可能会让人望而生畏,但这是一条有着文档、工具和社区支持的道路。我们将引导您完成整个过程,以便您可以通过示例学习。

这个教程是给谁的?

参见

如果您正在寻找有关编写代码的详细信息的参考资料,请参阅 编写代码 文件。

对于本教程,我们希望您至少对Django的工作方式有一个基本的了解。这意味着您应该能够轻松地阅读 writing your first Django app . 另外,您应该对Python本身有很好的了解。但如果你不这样做, `Dive Into Python`_ _是一本很棒的(免费的)在线书籍,适合于刚开始的Python程序员。

不熟悉版本控制系统和TRAC的人会发现,本教程及其链接仅包含足够的信息,可以开始学习。但是,如果你计划定期为Django做贡献的话,你可能会想更多地了解这些不同的工具。

不过,在大多数情况下,本教程会尽可能多地进行解释,以便对最广泛的读者有用。

从何处获得帮助:

如果您在阅读本教程时遇到困难,请在 Django Forum, django-developers, or drop by `#django-dev on irc.libera.chat`__ 与其他可能能提供帮助的Django用户聊天。

本教程涵盖哪些内容?

我们将带你第一次为德姜做一个补丁。在本教程的最后,您应该对所涉及的工具和过程有一个基本的了解。具体来说,我们将涵盖以下内容:

  • 安装GIT。

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

  • 运行Django的测试套件。

  • 为补丁编写测试。

  • 为您的补丁编写代码。

  • 测试你的补丁。

  • 提交请求。

  • 在哪里可以找到更多信息。

完成教程后,您可以查看 Django's documentation on contributing . 它包含了很多很好的信息,对于任何想成为DJANGO正式投稿人都是必读的。如果你有问题的话,很可能会有答案。

需要python 3!

Django的当前版本不支持Python2.7。获取Python 3 Python's download page 或者使用操作系统的包管理器。

对于Windows用户

安装Python 在Windows文档上获取更多指导。

行为守则

作为一个贡献者,你可以帮助我们保持Django社区的开放性和包容性。请阅读并遵循我们的 Code of Conduct .

安装GIT

对于本教程,您需要安装git来下载Django的当前开发版本,并为所做的更改生成补丁文件。

要检查是否安装了Git,请输入 git 进入命令行。如果收到消息说找不到该命令,则必须下载并安装该命令,请参阅 `Git's download page`_ _.

如果您不太熟悉git,您可以通过键入来了解它的命令(一旦安装了它)。 git help 进入命令行。

获取Django开发版本的副本

贡献给Django的第一步是获得源代码的副本。第一, fork Django on GitHub . 然后,从命令行使用 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项目测试您的本地更改可能很有帮助。首先,你必须创建一个新的虚拟环境, install the previously cloned local copy of Django in editable mode ,并在您本地的Django副本之外创建一个新的Django项目。您将在新项目中立即看到对Django所做的任何更改,这对编写您的第一个补丁非常有帮助,特别是在测试对UI的任何更改时。

您可以按照 tutorial 获取有关创建Django项目的帮助。

首次运行Django的测试套件

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

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

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

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

现在我们准备好运行测试套件了。如果您使用的是GNU/Linux、MacOS或其他风格的Unix,请运行:

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

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

当Django的测试套件运行时,您将看到一个代表每个测试完成时状态的字符流。 E 指示在测试过程中引发错误,以及 F 指示测试的断言失败。这两个都被认为是测试失败。与此同时, xs 分别指示预期故障和跳过的测试。点表示通过测试。

跳过的测试通常是由于缺少运行测试所需的外部库;请参见 运行所有测试 有关依赖项的列表,请确保安装任何与您所做更改相关的测试(本教程不需要任何测试)。某些测试特定于特定的数据库后端,如果不使用该后端进行测试,则将跳过这些测试。sqlite是默认设置的数据库后端。要使用其他后端运行测试,请参阅 使用另一个 settings 模块 .

一旦测试完成,您将收到一条消息,通知您测试套件是否通过。由于您还没有对django的代码进行任何更改,所以整个测试套件 应该 通过。如果您遇到故障或错误,请确保您已经正确地执行了前面的所有步骤。见 运行单元测试 更多信息。

请注意,最新的Django主分支可能并不总是稳定的。当针对“main”进行开发时,您可以检查 `Django's continuous integration builds`__ 以确定这些故障是否特定于您的计算机,或者它们是否也出现在Django的官方版本中。如果您点击查看特定的构建,您可以查看“配置矩阵”,其中显示了按Python版本和数据库后端细分的故障。

备注

对于本教程和我们正在开发的Ticket,针对SQLite进行测试就足够了,但是,有可能(有时也是必要的) run the tests using a different database 。更改用户界面时,您需要 run the Selenium tests

处理功能

在本教程中,我们将研究“假票”作为案例研究。以下是假想的细节:

门票99999——允许制作吐司

Django应该提供一个函数 django.shortcuts.make_toast() 它会回来 'toast' .

我们现在将实现这个特性和相关的测试。

为补丁创建分支

在进行任何更改之前,请为票据创建一个新分支:

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

您可以为分支选择任何名称,“ticket_99999”就是一个例子。此分支中所做的所有更改都将特定于通知单,并且不会影响我们先前复制的代码的主副本。

为你的票写一些测试

在大多数情况下,要想在Django中接受补丁,就必须包含测试。对于bug修复补丁,这意味着要编写一个回归测试,以确保该bug以后不会重新引入django。回归测试应该以这样的方式编写,即当错误仍然存在时,它将失败,并在错误修复后通过。对于包含新功能的补丁程序,您需要包括确保新功能正常工作的测试。当新特性不存在时,它们也应该失败,然后在实现后通过。

这样做的一个好方法是,在对代码进行任何更改之前,先编写新的测试。这种发展方式被称为 `test-driven development`_ _可以应用于整个项目和单个补丁。在编写测试之后,您将运行它们以确保它们确实失败(因为您还没有修复该bug或添加该特性)。如果你的新测试没有失败,你就需要修复它们,使它们成功。毕竟,不管是否存在bug,一个通过的回归测试对于防止这个bug在路上再次出现并不是很有帮助。

现在,以我们的实际操作为例。

为记录单编写测试99999

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

导航到Django's 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' .

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

如果你以前从未处理过测试,那么乍一看它们可能有点难写。幸运的是,测试是 very 计算机程序设计的大主题,因此有很多信息:

  • 有关如何编写Django的测试,请参见 编写和运行测试 .

  • 深入了解python(一本免费的在线书籍,面向入门级的python开发人员)包括 `introduction to Unit Testing`_ _.

  • 读完这些之后,如果你想吃点肉把你的牙齿塞进嘴里,总有 Python unittest 文档。

运行新测试

因为我们没有对 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测试套件以验证您的更改没有将任何bug引入到Django的其他区域是一个好主意。虽然成功通过整个测试套件并不能保证代码没有bug,但它确实有助于识别许多可能会被忽视的bug和回归。

要运行整个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

这将打开一个文本编辑器来键入提交消息。跟随 commit message guidelines 写一条信息,比如:

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

推送提交并发出请求

提交补丁后,将其发送到GitHub上的fork(如果不同,请将“ticket_999;99999”替换为分支名称):

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

您可以通过访问 Django GitHub page . 你会看到你的分支在“你最近推过的分支”下面。单击它旁边的“比较和拉请求”。

请不要在本教程中这样做,但是在显示补丁预览的下一页上,您将单击“创建拉请求”。

下一步

恭喜你,你已经学会了如何向Django发出请求了!您可能需要的更高级技术的详细信息在 使用Git和Github .

现在,您可以通过帮助改进Django的代码库来充分利用这些技能。

有关新参与者的详细信息

在你开始为Django编写补丁之前,你应该先看看关于贡献的更多信息:

找到你的第一张真正的票

一旦你浏览了其中的一些信息,你就可以出去找一张你自己的票来写一个补丁了。特别注意以“易选”为标准的门票。这些票在本质上通常简单得多,对于初次投稿人来说非常好。一旦你熟悉了对Django的贡献,你就可以继续为更困难和复杂的门票编写补丁了。

如果你只是想开始(没人会怪你!),尝试查看 `easy tickets that need patches`_`easy tickets that have patches which need improvement`_ ②如果您熟悉编写测试,还可以查看 `easy tickets that need tests`_ _. 记住要遵循Django文档链接中提到的关于申请机票的指南 claiming tickets and submitting patches .

创建拉请求之后接下来是什么?

当一张票有一个补丁后,需要用第二组眼睛检查它。提交请求后,通过在票据上设置标记来更新票据元数据,使其显示“有补丁”、“不需要测试”等,以便其他人可以找到它进行检查。贡献并不一定总是意味着从头开始写补丁。回顾现有的补丁也是一个非常有帮助的贡献。见 试用票 有关详细信息。