Стиль кодирования¶
Пожалуйста, следуйте этим стандартам кодирования при написании кода для включения в Django.
Проверки перед коммитом¶
pre-commit - это фреймворк для управления крючками предварительного коммита. Эти крючки помогают выявить простые проблемы перед передачей кода на проверку. Проверка этих проблем до проверки кода позволяет рецензенту сосредоточиться на самом изменении, а также может помочь сократить количество запусков CI.
Чтобы воспользоваться инструментом, сначала установите pre-commit
, а затем git hooks:
$ python -m pip install pre-commit
$ pre-commit install
...\> py -m pip install pre-commit
...\> pre-commit install
При первой фиксации pre-commit
установит хуки, они устанавливаются в собственном окружении и при первом запуске займут некоторое время. Последующие проверки будут выполняться значительно быстрее. При обнаружении ошибки будет выведено соответствующее сообщение об ошибке. Если ошибка была связана с black
или isort
, то инструмент исправит их за вас. Просмотрите изменения и повторно отправьте их на фиксацию, если они вас устраивают.
Стиль питона¶
Все файлы должны быть отформатированы с помощью автоформатера black. Он будет выполняться
pre-commit
, если он настроен.Репозиторий проекта включает файл
.editorconfig
. Мы рекомендуем использовать текстовый редактор с поддержкой EditorConfig, чтобы избежать проблем с отступами и пробелами. Файлы Python используют 4 пробела для отступов, а файлы HTML - 2 пробела.Если не указано иное, следуйте PEP 8.
Для проверки наличия проблем в этой области используйте flake8. Обратите внимание, что наш файл
setup.cfg
содержит некоторые исключенные файлы (устаревшие модули, которые мы не заботимся об очистке, и сторонний код, который поставляет Django), а также некоторые исключенные ошибки, которые мы не рассматриваем как грубые нарушения. Помните, что PEP 8 - это только руководство, поэтому соблюдение стиля окружающего кода является основной целью.Исключением из PEP 8 являются наши правила по длине строк. Не ограничивайте строки кода 79 символами, если это означает, что код выглядит значительно более уродливым или его труднее читать. Мы разрешаем до 88 символов, поскольку именно такая длина строки используется в
black
. Эта проверка включается при запускеflake8
. Документация, комментарии и docstrings должны быть обернуты в 79 символов, хотя PEP 8 предлагает 72.Интерполяция строковых переменных может использовать %-formatting, f-strings, или
str.format()
в зависимости от ситуации, с целью максимизации читабельности кода.Окончательные суждения о читабельности остаются на усмотрение Слияния. В качестве руководства, f-строки должны использовать только простой доступ к переменным и свойствам, с предварительным назначением локальных переменных для более сложных случаев:
# Allowed f"hello {user}" f"hello {user.name}" f"hello {self.user.name}" # Disallowed f"hello {get_user()}" f"you are {user.age * 365.25} days old" # Allowed with local variable assignment user = get_user() f"hello {user}" user_days_old = user.age * 365.25 f"you are {user_days_old} days old"
f-строки не следует использовать для любых строк, которые могут потребовать перевода, включая сообщения об ошибках и протоколирования. В общем случае
format()
является более многословным, поэтому предпочтительнее использовать другие методы форматирования.Не тратьте время на несвязный рефакторинг существующего кода для настройки метода форматирования.
Избегайте использования «мы» в комментариях, например, «Loop over», а не «We loop over».
Используйте подчеркивание, а не camelCase, для имен переменных, функций и методов (т.е.
poll.get_unique_voters()
, а неpoll.getUniqueVoters()
).Используйте
InitialCaps
для имен классов (или для фабричных функций, которые возвращают классы).В документах следуйте стилю существующих документов и PEP 257.
В тестах используйте
assertRaisesMessage()
иassertWarnsMessage()
вместоassertRaises()
иassertWarns()
, чтобы вы могли проверить исключение или предупреждающее сообщение. ИспользуйтеassertRaisesRegex()
иassertWarnsRegex()
только в том случае, если вам необходимо сопоставление регулярных выражений.Для проверки булевых значений используйте
assertIs(…, True/False)
, а неassertTrue()
иassertFalse()
, чтобы можно было проверить фактическое булево значение, а не истинность выражения.В тестовых документах указывайте ожидаемое поведение, которое демонстрирует каждый тест. Не включайте преамбулы типа «Проверяет, что» или «Обеспечивает, что».
Резервируйте ссылки на билеты для неясных проблем, когда билет имеет дополнительные детали, которые не могут быть легко описаны в документах или комментариях. Включите номер тикета в конец предложения, например, так:
def test_foo(): """ A test docstring looks like this (#123456). """ ...
Импорт¶
Используйте isort для автоматизации сортировки импорта, используя приведенные ниже рекомендации.
Быстрый старт:
$ python -m pip install "isort >= 5.1.0" $ isort .
...\> py -m pip install "isort >= 5.1.0" ...\> isort .
Это запускает
isort
рекурсивно из вашего текущего каталога, изменяя все файлы, которые не соответствуют рекомендациям. Если вам нужно, чтобы импорт выполнялся не по порядку (например, чтобы избежать циклического импорта), используйте комментарий, подобный этому:import module # isort:skip
Поместите импорт в эти группы: future, standard library, third-party libraries, other Django components, local Django component, try/excepts. Сортируйте строки в каждой группе в алфавитном порядке по полному имени модуля. Поместите все утверждения
import module
передfrom module import objects
в каждой секции. Используйте абсолютный импорт для других компонентов Django и относительный импорт для локальных компонентов.На каждой строке расположите элементы в алфавитном порядке так, чтобы элементы в верхнем регистре были сгруппированы перед элементами в нижнем регистре.
Разрывайте длинные строки с помощью круглых скобок и отступайте от них на 4 пробела. Поставьте запятую после последнего импорта и поместите закрывающую скобку на отдельной строке.
Используйте одну пустую строку между последним импортом и любым кодом на уровне модуля, а также используйте две пустые строки над первой функцией или классом.
Например (комментарии приведены только для пояснения):
# future from __future__ import unicode_literals # standard library import json from itertools import chain # third-party import bcrypt # Django from django.http import Http404 from django.http.response import ( Http404, HttpResponse, HttpResponseNotAllowed, StreamingHttpResponse, cookie, ) # local Django from .models import LogEntry # try/except try: import yaml except ImportError: yaml = None CONSTANT = "foo" class Example: ...
Использовать удобный импорт при любой возможности. Например, сделайте так
from django.views import View
вместо:
from django.views.generic.base import View
Стиль шаблона¶
В коде шаблона Django ставьте один (и только один) пробел между фигурными скобками и содержимым тега.
Сделайте это:
{{ foo }}
Не делайте этого:
{{foo}}
Вид стиля¶
В представлениях Django первый параметр в функции представления должен называться
request
.Сделайте следующее:
def my_view(request, foo): ...
Не делайте этого:
def my_view(req, foo): ...
Стиль модели¶
Имена полей должны быть полностью строчными, с использованием подчеркивания вместо camelCase.
Сделайте следующее:
class Person(models.Model): first_name = models.CharField(max_length=20) last_name = models.CharField(max_length=40)
Не делайте этого:
class Person(models.Model): FirstName = models.CharField(max_length=20) Last_Name = models.CharField(max_length=40)
Строка
class Meta
должна появляться после определения полей, с одной пустой строкой, разделяющей поля и определение класса.Сделайте следующее:
class Person(models.Model): first_name = models.CharField(max_length=20) last_name = models.CharField(max_length=40) class Meta: verbose_name_plural = "people"
Не делайте этого:
class Person(models.Model): class Meta: verbose_name_plural = "people" first_name = models.CharField(max_length=20) last_name = models.CharField(max_length=40)
Порядок внутренних классов модели и стандартных методов должен быть следующим (обратите внимание, что не все они являются обязательными):
- Все поля базы данных
- Пользовательские атрибуты менеджера
class Meta
def __str__()
def save()
def get_absolute_url()
- Любые пользовательские методы
Если для данного поля модели определено
choices
, определите каждый выбор как отображение, с именем во всех верхних регистрах в качестве атрибута класса модели. Пример:class MyModel(models.Model): DIRECTION_UP = "U" DIRECTION_DOWN = "D" DIRECTION_CHOICES = { DIRECTION_UP: "Up", DIRECTION_DOWN: "Down", }
В качестве альтернативы можно использовать Типы перечисления:
class MyModel(models.Model): class Direction(models.TextChoices): UP = U, "Up" DOWN = D, "Down"
Использование django.conf.settings
¶
Модули в общем случае не должны использовать настройки, хранящиеся в django.conf.settings
на верхнем уровне (т.е. оцениваемые при импорте модуля). Это объясняется следующим образом:
Ручная конфигурация настроек (т.е. не полагаясь на переменную окружения DJANGO_SETTINGS_MODULE
) разрешена и возможна следующим образом:
from django.conf import settings
settings.configure({}, SOME_SETTING="foo")
Однако, если доступ к любой настройке осуществляется до строки settings.configure
, это не сработает. (Внутри settings
является LazyObject
, который автоматически конфигурируется при обращении к настройкам, если он еще не был сконфигурирован).
Итак, если имеется модуль, содержащий некоторый код следующего вида:
from django.conf import settings
from django.urls import get_callable
default_foo_view = get_callable(settings.FOO_VIEW)
то импорт этого модуля приведет к конфигурированию объекта настроек. Это означает, что возможность импорта модуля третьими лицами на верхнем уровне несовместима с возможностью конфигурировать объект настроек вручную, или делает это очень сложным в некоторых обстоятельствах.
Вместо приведенного выше кода следует использовать уровень лени или косвенности, например django.utils.functional.LazyObject
, django.utils.functional.lazy()
или lambda
.
Разное¶
- Пометить все строки для интернационализации; подробности см. в i18n documentation.
- При изменении кода удалите операторы
import
, которые больше не используются. flake8 сам определит эти импорты. Если неиспользуемый импорт должен остаться для обеспечения обратной совместимости, пометьте конец# NOQA
, чтобы заглушить предупреждение flake8. - Систематически удаляйте из кода все пробелы в конце кода, поскольку они добавляют ненужные байты, визуально загромождают патчи и иногда могут вызывать ненужные конфликты слияния. Некоторые IDE могут быть настроены на автоматическое удаление пробелов, а большинство инструментов VCS могут быть настроены на их выделение в результатах различий.
- Пожалуйста, не указывайте свое имя в коде, который вы предоставляете. Наша политика заключается в том, чтобы имена участников были указаны в файле
AUTHORS
, распространяемом вместе с Django - а не разбросаны по всей кодовой базе. Не стесняйтесь включать изменения в файлAUTHORS
в свой патч, если вы вносите более чем одно тривиальное изменение.
Стиль JavaScript¶
Подробнее о стиле кода JavaScript, используемом в Django, смотрите JavaScript.