Стиль кодирования¶
Пожалуйста, следуйте этим стандартам кодирования при написании кода для включения в 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
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 black
or 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.
Стиль питона¶
Все файлы должны быть отформатированы с помощью автоформатера black. Это будет выполняться
pre-commit
, если он настроен.The project repository includes an
.editorconfig
file. We recommend using a text editor with EditorConfig support to avoid indentation and whitespace issues. The Python files use 4 spaces for indentation and the HTML files use 2 spaces.Если не указано иное, следуйте PEP 8.
Используйте flake8 для проверки проблем в этой области. Обратите внимание, что наш файл
setup.cfg
содержит некоторые исключенные файлы (устаревшие модули, об очистке которых мы не заботимся, и некоторый сторонний код, который поставляется Django), а также некоторые исключенные ошибки, которые мы не считаем грубыми нарушениями. Помните, что PEP 8 - это только руководство, поэтому соблюдение стиля окружающего кода является главной целью.An exception to PEP 8 is our rules on line lengths. Don’t limit lines of code to 79 characters if it means the code looks significantly uglier or is harder to read. We allow up to 88 characters as this is the line length used by
black
. This check is included when you runflake8
. Documentation, comments, and docstrings should be wrapped at 79 characters, even though PEP 8 suggests 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). """ ...
Импорт¶
Use isort to automate import sorting using the guidelines below.
Быстрый старт:
$ 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.