Написание вашего первого патча для Django

Вступление

Хотите немного помочь сообществу? Возможно, вы нашли ошибку в Django, которую вы хотели бы увидеть исправленной, или, может быть, есть небольшая функция, которую вы хотите добавить.

Вклад в развитие самого Django - лучший способ увидеть, как решаются ваши собственные проблемы. Поначалу это может показаться сложным, но это хорошо проторенный путь с документацией, инструментарием и сообществом, которое вас поддержит. Мы проведем вас через весь процесс, чтобы вы могли учиться на собственном примере.

Для кого этот учебник?

См.также

Если вы ищете справочник по деталям внесения кода, обратитесь к документации Написание кода.

Для этого учебника мы ожидаем, что у вас есть хотя бы базовое понимание того, как работает Django. Это означает, что вам должно быть удобно изучать существующие учебники по writing your first Django app. Кроме того, у вас должно быть хорошее понимание самого языка Python. Но если у вас его нет, Dive Into Python - это фантастическая (и бесплатная) онлайн книга для начинающих программистов на Python.

Те из вас, кто не знаком с системами контроля версий и Trac, найдут, что это руководство и его ссылки содержат достаточно информации для начала работы. Однако, если вы планируете регулярно вносить свой вклад в Django, вам, вероятно, захочется прочитать еще немного об этих различных инструментах.

Однако, по большей части, это руководство старается объяснить как можно больше, чтобы оно могло быть полезным для самой широкой аудитории.

Где можно получить помощь:

Если у вас возникли трудности при прохождении этого руководства, пожалуйста, напишите сообщение на Django Forum, django-developers, или зайдите на #django-dev on irc.libera.chat, чтобы пообщаться с другими пользователями Django, которые могут помочь.

О чем рассказывается в этом учебнике?

Мы проведем вас через первый опыт внесения патча в Django. К концу этого урока у вас должно быть базовое понимание как инструментов, так и процессов. В частности, мы рассмотрим следующее:

  • Установка Git.
  • Загрузка копии версии Django для разработки.
  • Запуск тестового пакета Django.
  • Написание теста для вашего патча.
  • Написание кода для вашего патча.
  • Тестирование вашего патча.
  • Подача запроса на исправление.
  • Где искать дополнительную информацию.

Как только вы закончите с этим учебником, вы можете просмотреть остальную часть Django’s documentation on contributing. Он содержит много замечательной информации и является обязательным к прочтению для всех, кто хочет стать постоянным автором Django. Если у вас есть вопросы, здесь наверняка есть ответы.

Требуется Python 3!

Текущая версия Django не поддерживает Python 2.7. Получите Python 3 по адресу Python’s download page или с помощью менеджера пакетов вашей операционной системы.

Для пользователей Windows

Дополнительное руководство см. в документации по Windows Установите Python.

Кодекс поведения

Как участник, вы можете помочь нам сохранить сообщество 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 МБ до ~70 МБ.

Теперь, когда у вас есть локальная копия 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, в вашем новом проекте, что очень поможет при написании вашего первого патча.

Запуск тестового пакета Django в первый раз

При внесении вклада в Django очень важно, чтобы ваши изменения кода не привели к ошибкам в других областях 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. Обратитесь к документации по неудачному пакету или найдите в Интернете сообщение об ошибке, с которой вы столкнулись.

Теперь мы готовы запустить набор тестов. Если вы используете GNU/Linux, macOS или другой вариант Unix, запустите:

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

Теперь сядьте поудобнее и расслабьтесь. Весь набор тестов Django насчитывает тысячи тестов, и его выполнение занимает не менее нескольких минут, в зависимости от скорости вашего компьютера.

Во время работы набора тестов Django вы увидите поток символов, отражающих статус каждого теста по мере его завершения. E означает, что во время теста возникла ошибка, а F означает, что утверждения теста не сработали. И то, и другое считается неудачей теста. Между тем, x и s означают ожидаемые неудачи и пропущенные тесты, соответственно. Точки указывают на прохождение тестов.

Пропущенные тесты обычно связаны с отсутствием внешних библиотек, необходимых для выполнения теста; смотрите Выполнение всех тестов для списка зависимостей и убедитесь, что все они установлены для тестов, связанных с изменениями, которые вы делаете (для этого руководства они нам не понадобятся). Некоторые тесты специфичны для определенного бэкенда баз данных и будут пропущены, если тестирование проводится не с этим бэкендом. SQLite является бэкендом базы данных для настроек по умолчанию. Чтобы запустить тесты с использованием другого бэкенда, смотрите Использование другого модуля settings.

После завершения тестов вас должно встретить сообщение, информирующее вас о том, прошел или не прошел набор тестов. Поскольку вы еще не внесли никаких изменений в код Django, весь набор тестов должен пройти. Если вы получаете неудачи или ошибки, убедитесь, что вы правильно выполнили все предыдущие шаги. Смотрите Запуск модульных тестов для получения дополнительной информации.

Обратите внимание, что последняя ветка Django «main» не всегда может быть стабильной. При разработке на «main», вы можете проверить Django’s continuous integration builds, чтобы определить, являются ли сбои специфичными для вашей машины или они также присутствуют в официальных сборках Django. Если вы щелкните для просмотра конкретной сборки, вы можете просмотреть «Матрицу конфигурации», которая показывает сбои в разбивке по версии Python и бэкенду базы данных.

Примечание

Для этого учебника и тикета, над которым мы работаем, достаточно тестирования на SQLite, однако можно (и иногда необходимо) run the tests using a different database.

Работа над функцией

В этом учебнике мы будем работать с «фальшивым билетом» в качестве примера. Вот воображаемые детали:

Билет #99999 – Разрешить приготовление тостов

Django должен предоставить функцию django.shortcuts.make_toast(), которая возвращает 'toast'.

Теперь мы реализуем эту функцию и связанные с ней тесты.

Создание ответвления для вашего патча

Прежде чем вносить какие-либо изменения, создайте новую ветку для билета:

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

Вы можете выбрать любое имя для ветки, например, «ticket_99999». Все изменения, сделанные в этой ветке, будут касаться только тикета и не повлияют на основную копию кода, которую мы клонировали ранее.

Написание нескольких тестов для вашего билета

В большинстве случаев, чтобы патч был принят в Django, он должен включать тесты. Для патчей, исправляющих ошибки, это означает написание регрессионного теста, чтобы гарантировать, что ошибка никогда не будет повторно внесена в Django позже. Регрессионный тест должен быть написан таким образом, чтобы он был провален, пока ошибка еще существует, и пройден, когда ошибка будет исправлена. Для патчей, содержащих новые возможности, вам нужно будет включить тесты, проверяющие правильность работы новых возможностей. Они тоже должны выходить из строя, когда новая функция отсутствует, и проходить после ее внедрения.

Хороший способ сделать это - сначала написать новые тесты, прежде чем вносить какие-либо изменения в код. Такой стиль разработки называется test-driven development и может применяться как к целым проектам, так и к отдельным патчам. После написания тестов вы запускаете их, чтобы убедиться, что они действительно не работают (поскольку вы еще не исправили ошибку или не добавили функцию). Если ваши новые тесты не сработали, вам нужно исправить их так, чтобы они сработали. В конце концов, регрессионный тест, который проходит независимо от наличия ошибки, не очень полезен для предотвращения ее повторного появления в будущем.

Теперь перейдем к нашему практическому примеру.

Написание теста для билета #99999

Чтобы решить эту проблему, мы добавим функцию make_toast() в модуль django.shortcuts. Сначала мы напишем тест, который попытается использовать функцию и проверим, что ее вывод выглядит корректно.

Перейдите в папку 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 можно найти в документации по Написание и выполнение тестов.
  • Dive Into 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, чтобы убедиться, что ваше изменение не внесло никаких ошибок в другие области 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. Добавьте заметку под заголовком «Minor Features»:

: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 (замените «ticket_99999» на название вашего филиала, если оно другое):

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

Вы можете создать pull request, посетив страницу Django GitHub page. Вы увидите свою ветку в разделе «Your recently pushed branches». Нажмите «Compare & pull request» рядом с ней.

Пожалуйста, не делайте этого для данного руководства, но на следующей странице, где отображается предварительный просмотр патча, вы должны нажать «Create pull request».

Следующие шаги

Поздравляем, вы узнали, как сделать pull request в Django! Подробности более продвинутых методов, которые могут вам понадобиться, находятся в Работа с Git и GitHub.

Теперь вы можете применить эти навыки на практике, помогая совершенствовать кодовую базу Django.

Дополнительная информация для новых вкладчиков

Прежде чем вы начнете писать патчи для Django, вам стоит ознакомиться с дополнительной информацией о внесении вкладов:

  • Вы должны обязательно прочитать документацию Django на claiming tickets and submitting patches. В ней рассказывается об этикете Trac, о том, как требовать тикеты для себя, о предполагаемом стиле кодирования патчей и о многих других важных деталях.
  • Начинающим контрибьюторам также следует прочитать статью Django documentation for first time contributors. Там есть много хороших советов для тех из нас, кто только начинает помогать в работе с Django.
  • После этого, если вы все еще хотите получить больше информации о внесении взносов, вы всегда можете просмотреть остальную часть Django’s documentation on contributing. Он содержит массу полезной информации и должен стать вашим первым источником ответов на любые вопросы, которые у вас могут возникнуть.

Найти свой первый настоящий билет

После того как вы просмотрите часть этой информации, вы будете готовы отправиться на поиски собственного билета для написания исправления. Обратите особое внимание на билеты с критерием «легкая добыча». Эти билеты часто намного проще по своей природе и отлично подходят для начинающих авторов. Когда вы освоитесь с внесением вклада в 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.

Что делать дальше после создания запроса на исправление?

После того, как в билет внесено исправление, его необходимо просмотреть вторым взглядом. После отправки запроса на исправление обновите метаданные тикета, установив в нем флаги «есть патч», «не нуждается в тестах» и т.д., чтобы другие могли найти его для проверки. Вклад не обязательно всегда означает написание патча с нуля. Рецензирование существующих патчей также является очень полезным вкладом. Подробности смотрите в Учет заявок.

Вернуться на верх