编码风格

编写代码以包含在Django中时,请遵循这些编码标准。

提交前检查

pre-commit 是一个用于管理提交前挂钩的框架。这些挂钩有助于在提交代码以供审查之前识别简单的问题。通过在代码审查之前检查这些问题,审查者可以将注意力集中在更改本身上,还可以帮助减少CI运行的数量。

要使用该工具,请先安装 pre-commit 然后这个下巴就钩住了:

$ python -m pip install pre-commit
$ pre-commit install
...\> py -m pip install pre-commit
...\> pre-commit install

在第一次提交时 pre-commit 将安装这些钩子,这些钩子安装在它们自己的环境中,在第一次运行时需要一段时间才能安装。后续检查将大大加快速度。如果发现错误,则会显示相应的错误消息。如果错误是与 blackisort 然后,该工具将继续为您修复它们。如果您对更改满意,请查看更改并重新提交。

Python 式

  • 所有文件都应使用 black 自动格式化程序。这项工作将由 pre-commit 如果已配置的话。

  • 项目存储库包括一个 .editorconfig 文件。我们建议将文本编辑器与 EditorConfig 支持避免缩进和空格问题。Python文件使用4个空格进行缩进,而HTML文件使用2个空格。

  • 除非另有规定,遵循 PEP 8 .

    使用 flake8 以检查此区域中的问题。请注意,我们的 setup.cfg 文件包含一些被排除的文件(我们不在乎清理的过时模块和一些Django供应商的第三方代码),以及一些我们不认为是严重违规的被排除的错误。记住 PEP 8 只是一个指南,因此将尊重周围代码的样式作为主要目标。

    例外于 PEP 8 是我们对线路长度的规定。不要将代码行数限制在79个字符以内,如果这意味着代码看起来更难看或更难读。我们最多允许88个字符,因为这是使用的行长 black 。当您运行时,将包括此检查 flake8 。文档、注释和文档字符串应以79个字符换行,即使 PEP 8 显示为72岁。

  • 字符串变量插值可以使用 %-formattingf-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() 更加冗长,因此首选其他格式设置方法。

    不要浪费时间对现有代码进行不相关的重构来调整格式化方法。

  • 避免在注释中使用“we”,例如“loop over”而不是“we loop over”。

  • 变量、函数和方法名(即 poll.get_unique_voters() 不是 poll.getUniqueVoters()

  • 使用 InitialCaps 用于类名(或用于返回类的工厂函数)。

  • 在DocStrings中,遵循现有DocStrings的样式和 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
    
  • 将导入放在以下组中:未来、标准库、第三方库、其他Django组件、本地Django组件、Try/Excepts。按模块全名的字母顺序对每个组中的行进行排序。全部放置 import module 之前的陈述 from module import objects 在每个部分。对其他Django组件使用绝对导入,对本地组件使用相对导入。

  • 在每一行中,按字母顺序排列项目,将大写项目分组在小写项目之前。

  • 使用圆括号分隔长线,并将续行缩进4个空格。在最后一次导入后包含尾随逗号,并将右括号放在自己的行上。

    在最后一次导入和任何模块级代码之间使用一个空行,并在第一个函数或类上方使用两个空行。

    例如(注释仅供解释):

    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:
        ...
    
  • 只要有方便的进口,就使用它。例如,执行以下操作::

    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.LazyObjectdjango.utils.functional.lazy()lambda .

其他

  • 标记国际化的所有字符串;请参见 i18n documentation 有关详细信息。

  • 移除 import 更改代码时不再使用的语句。 flake8 将为您识别这些进口产品。如果需要保留未使用的导入以实现向后兼容,请使用 # NOQA 让雪花般的警告安静下来。

  • 系统地从代码中删除所有尾随的空白,因为这些空白添加了不必要的字节,给补丁添加了视觉混乱,并且偶尔也会导致不必要的合并冲突。一些IDE可以配置为自动删除它们,大多数VCS工具可以设置为在diff输出中突出显示它们。

  • 请不要把你的名字写在你的代码里。我们的政策是在 AUTHORS 使用django分发的文件——不分散在代码库本身。请随意更改 AUTHORS 如果您做了不止一个微不足道的更改,请将文件保存在补丁中。

JavaScript样式

有关Django使用的javascript代码样式的详细信息,请参见 JavaScript .