mirror of
				https://github.com/django/django.git
				synced 2025-10-26 07:06:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			340 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			340 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| ============
 | |
| 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/
 |