Стиль кодирования¶
Пожалуйста, следуйте этим стандартам кодирования при написании кода для включения в Django.
Проверки перед коммитом¶
pre-commit is a framework for managing pre-commit hooks. These hooks help to identify simple issues before committing code for review. By checking for these issues before code review it allows the reviewer to focus on the change itself, and it can also help to reduce the number of CI runs.
Чтобы воспользоваться инструментом, сначала установите pre-commit
, а затем git hooks:
$ python -m pip install pre-commit
$ pre-commit install
...\> py -m pip install pre-commit
...\> pre-commit install
On the first commit pre-commit
will install the hooks, these are
installed in their own environments and will take a short while to
install on the first run. Subsequent checks will be significantly faster.
If an error is found an appropriate error message will be displayed.
If the error was with isort
then the tool will go ahead and fix them for
you. Review the changes and re-stage for commit if you are happy with
them.
Стиль питона¶
Пожалуйста, соблюдайте стиль отступов, продиктованный в файле
.editorconfig
. Мы рекомендуем использовать текстовый редактор с поддержкой EditorConfig, чтобы избежать проблем с отступами и пробелами. В файлах Python для отступов используется 4 пробела, а в файлах HTML - 2 пробела.Если не указано иное, следуйте PEP 8.
Используйте flake8 для проверки проблем в этой области. Обратите внимание, что наш файл
setup.cfg
содержит некоторые исключенные файлы (устаревшие модули, об очистке которых мы не заботимся, и некоторый сторонний код, который поставляется Django), а также некоторые исключенные ошибки, которые мы не считаем грубыми нарушениями. Помните, что PEP 8 - это только руководство, поэтому соблюдение стиля окружающего кода является главной целью.Исключением из PEP 8 являются наши правила по длине строк. Не ограничивайте строки кода 79 символами, если это означает, что код выглядит значительно более уродливым или его труднее читать. Мы разрешаем до 119 символов, поскольку это ширина обзора кода на GitHub; все, что длиннее, требует горизонтальной прокрутки, что затрудняет обзор. Эта проверка включается, когда вы выполняете
flake8
. Документация, комментарии и docstrings должны быть обернуты в 79 символов, хотя PEP 8 предлагает 72.Используйте четыре пробела для отступа.
Используйте отступ в четыре интервала, а не вертикальное выравнивание:
raise AttributeError( 'Here is a multiline error message ' 'shortened for clarity.' )
Вместо:
raise AttributeError('Here is a multiline error message ' 'shortened for clarity.')
Это позволяет лучше использовать пространство и избежать необходимости выравнивания строк при изменении длины первой строки.
Используйте одинарные кавычки для строк, или двойную кавычку, если строка содержит одинарную кавычку. Не тратьте время на несвязный рефакторинг существующего кода, чтобы привести его в соответствие с этим стилем.
Интерполяция строковых переменных может использовать :py<<<<0 >>>, :py<<<<1 >>>, или :py<<<<2 >>> в зависимости от ситуации, с целью максимизации читабельности кода.
Окончательные суждения о читабельности остаются на усмотрение Слияния. В качестве руководства, 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): 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'), ]
Использование 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.