123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- ============
- Coding style
- ============
- Please follow these coding standards when writing code for inclusion in Django.
- .. _coding-style-python:
- Python style
- ============
- * Please conform to the indentation style dictated in the ``.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.
- * Unless otherwise specified, follow :pep:`8`.
- Use `flake8`_ to check for problems in this area. Note that our ``setup.cfg``
- file contains some excluded files (deprecated modules we don't care about
- cleaning up and some third-party code that Django vendors) as well as some
- excluded errors that we don't consider as gross violations. Remember that
- :pep:`8` is only a guide, so respect the style of the surrounding code as a
- primary goal.
- 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 119 characters as this is the width of GitHub
- code review; anything longer requires horizontal scrolling which makes review
- more difficult. This check is included when you run ``flake8``. Documentation,
- comments, and docstrings should be wrapped at 79 characters, even though
- :pep:`8` suggests 72.
- * Use four spaces for indentation.
- * Use four space hanging indentation rather than vertical alignment::
- raise AttributeError(
- 'Here is a multine error message '
- 'shortened for clarity.'
- )
- Instead of::
- raise AttributeError('Here is a multine error message '
- 'shortened for clarity.')
- This makes better use of space and avoids having to realign strings if the
- length of the first line changes.
- * Use single quotes for strings, or a double quote if the string contains a
- single quote. Don't waste time doing unrelated refactoring of existing code
- to conform to this style.
- * Avoid use of "we" in comments, e.g. "Loop over" rather than "We loop over".
- * Use underscores, not camelCase, for variable, function and method names
- (i.e. ``poll.get_unique_voters()``, not ``poll.getUniqueVoters()``).
- * Use ``InitialCaps`` for class names (or for factory functions that
- return classes).
- * In docstrings, follow the style of existing docstrings and :pep:`257`.
- * In tests, use
- :meth:`~django.test.SimpleTestCase.assertRaisesMessage` and
- :meth:`~django.test.SimpleTestCase.assertWarnsMessage`
- instead of :meth:`~unittest.TestCase.assertRaises` and
- :meth:`~unittest.TestCase.assertWarns` so you can check the
- exception or warning message. Use :meth:`~unittest.TestCase.assertRaisesRegex`
- and :meth:`~unittest.TestCase.assertWarnsRegex` only if you need regular
- expression matching.
- * In test docstrings, state the expected behavior that each test demonstrates.
- Don't include preambles such as "Tests that" or "Ensures that".
- Reserve ticket references for obscure issues where the ticket has additional
- details that can't be easily described in docstrings or comments. Include the
- ticket number at the end of a sentence like this::
- def test_foo():
- """
- A test docstring looks like this (#123456).
- """
- ...
- .. _coding-style-imports:
- Imports
- =======
- * Use `isort <https://github.com/timothycrosley/isort#readme>`_ to automate
- import sorting using the guidelines below.
- Quick start:
- .. console::
- $ pip install isort
- $ isort -rc .
- This runs ``isort`` recursively from your current directory, modifying any
- files that don't conform to the guidelines. If you need to have imports out
- of order (to avoid a circular import, for example) use a comment like this::
- import module # isort:skip
- * Put imports in these groups: future, standard library, third-party libraries,
- other Django components, local Django component, try/excepts. Sort lines in
- each group alphabetically by the full module name. Place all ``import module``
- statements before ``from module import objects`` in each section. Use absolute
- imports for other Django components and relative imports for local components.
- * On each line, alphabetize the items with the upper case items grouped before
- the lower case items.
- * Break long lines using parentheses and indent continuation lines by 4 spaces.
- Include a trailing comma after the last import and put the closing
- parenthesis on its own line.
- Use a single blank line between the last import and any module level code,
- and use two blank lines above the first function or class.
- For example (comments are for explanatory purposes only):
- .. snippet::
- :filename: django/contrib/admin/example.py
- # 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:
- # ...
- * Use convenience imports whenever available. For example, do this::
- from django.views import View
- instead of::
- from django.views.generic.base import View
- Template style
- ==============
- * In Django template code, put one (and only one) space between the curly
- brackets and the tag contents.
- Do this:
- .. code-block:: html+django
- {{ foo }}
- Don't do this:
- .. code-block:: html+django
- {{foo}}
- View style
- ==========
- * In Django views, the first parameter in a view function should be called
- ``request``.
- Do this::
- def my_view(request, foo):
- # ...
- Don't do this::
- def my_view(req, foo):
- # ...
- Model style
- ===========
- * Field names should be all lowercase, using underscores instead of
- camelCase.
- Do this::
- class Person(models.Model):
- first_name = models.CharField(max_length=20)
- last_name = models.CharField(max_length=40)
- Don't do this::
- class Person(models.Model):
- FirstName = models.CharField(max_length=20)
- Last_Name = models.CharField(max_length=40)
- * The ``class Meta`` should appear *after* the fields are defined, with
- a single blank line separating the fields and the class definition.
- Do this::
- class Person(models.Model):
- first_name = models.CharField(max_length=20)
- last_name = models.CharField(max_length=40)
- class Meta:
- verbose_name_plural = 'people'
- Don't do this::
- class Person(models.Model):
- first_name = models.CharField(max_length=20)
- last_name = models.CharField(max_length=40)
- class Meta:
- verbose_name_plural = 'people'
- Don't do this, either::
- class Person(models.Model):
- class Meta:
- verbose_name_plural = 'people'
- first_name = models.CharField(max_length=20)
- last_name = models.CharField(max_length=40)
- * The order of model inner classes and standard methods should be as
- follows (noting that these are not all required):
- * All database fields
- * Custom manager attributes
- * ``class Meta``
- * ``def __str__()``
- * ``def save()``
- * ``def get_absolute_url()``
- * Any custom methods
- * If ``choices`` is defined for a given model field, define each choice as
- a tuple of tuples, with an all-uppercase name as a class attribute on the
- model. Example::
- class MyModel(models.Model):
- DIRECTION_UP = 'U'
- DIRECTION_DOWN = 'D'
- DIRECTION_CHOICES = (
- (DIRECTION_UP, 'Up'),
- (DIRECTION_DOWN, 'Down'),
- )
- Use of ``django.conf.settings``
- ===============================
- Modules should not in general use settings stored in ``django.conf.settings``
- at the top level (i.e. evaluated when the module is imported). The explanation
- for this is as follows:
- Manual configuration of settings (i.e. not relying on the
- ``DJANGO_SETTINGS_MODULE`` environment variable) is allowed and possible as
- follows::
- from django.conf import settings
- settings.configure({}, SOME_SETTING='foo')
- However, if any setting is accessed before the ``settings.configure`` line,
- this will not work. (Internally, ``settings`` is a ``LazyObject`` which
- configures itself automatically when the settings are accessed if it has not
- already been configured).
- So, if there is a module containing some code as follows::
- from django.conf import settings
- from django.urls import get_callable
- default_foo_view = get_callable(settings.FOO_VIEW)
- ...then importing this module will cause the settings object to be configured.
- That means that the ability for third parties to import the module at the top
- level is incompatible with the ability to configure the settings object
- manually, or makes it very difficult in some circumstances.
- Instead of the above code, a level of laziness or indirection must be used,
- such as ``django.utils.functional.LazyObject``,
- ``django.utils.functional.lazy()`` or ``lambda``.
- Miscellaneous
- =============
- * Mark all strings for internationalization; see the :doc:`i18n
- documentation </topics/i18n/index>` for details.
- * Remove ``import`` statements that are no longer used when you change code.
- `flake8`_ will identify these imports for you. If an unused import needs to
- remain for backwards-compatibility, mark the end of with ``# NOQA`` to
- silence the flake8 warning.
- * Systematically remove all trailing whitespaces from your code as those
- add unnecessary bytes, add visual clutter to the patches and can also
- occasionally cause unnecessary merge conflicts. Some IDE's can be
- configured to automatically remove them and most VCS tools can be set to
- highlight them in diff outputs.
- * Please don't put your name in the code you contribute. Our policy is to
- keep contributors' names in the ``AUTHORS`` file distributed with Django
- -- not scattered throughout the codebase itself. Feel free to include a
- change to the ``AUTHORS`` file in your patch if you make more than a
- single trivial change.
- JavaScript style
- ================
- For details about the JavaScript code style used by Django, see
- :doc:`javascript`.
- .. _editorconfig: http://editorconfig.org/
- .. _flake8: https://pypi.org/project/flake8/
|