Django Coding Style

编写Django中的代码时,请遵循下列编码风格

Python编码风格

  • 请遵循editorconfig文件中制定的缩进样式,建议使用支持 EditConfig 的编辑器,以避免缩进和空格方面的问题。Python源代码文件使用4个空格的缩进,HTML文件用2个空格的缩进。

  • 除非特别声明,请遵循 PEP 8

使用 flake8 自动检查。请注意我们提供的setup.cfg文件中包含了一些不需要检查的文件(如:弃用的文件、可清理文件和第三方提供的django代码),和一些我们不认为是严重违规的错误。应当记住 PEP 8 只是起指导作用,主要是要遵循代码中已形成的编码风格。

一个不需要遵循 PEP 8的例外为行的长度,如果看起来明显很丑或者难以阅读,请不要限定每一行的长度为79,我们允许想Github 代码评审那样,可以最高每行容纳119个字符,再长就需要水平滚动了,这样会使代码review更费劲。运行flake8时应当包含这个。

文档、注释、docstring应当限定为79个字符,虽然 PEP 8的建议为72个。

  • 使用四个空格作为缩进,勿使用tab

  • 使用四个空格缩进,而非垂直对其,如:

建议:

1
2
3
4
raise AttributeError(
'Here is a multine error message '
'shortened for clarity.'
)

不建议:

1
2
raise AttributeError('Here is a multine error message '
'shortened for clarity.')

这样可以更好的利用空间,还能避免第一行的长度变化时引起的后续行的变动。

  • 字符串使用单引号包裹,如果字符串包含单引号时采用双引号。但是在写代码时,不要去重构不相关处的代码,有点浪费时间。

  • 不要在注释中写”we”。如”We loop over.”应该改成”Loop over.”

  • 变量名、函数名、方法名使用下划线链接单词,不要使用驼峰。如poll.get_unique_voters(),而非poll.getUniqueVoters()

  • 使用InitalCaps方式去命名类名

  • docstring遵循现有风格,以及 PEP 257

  • 在测试中,使用 assertRaisesMessage()assertWarnsMessage(),而非assertRaises()assertWarns(),这样可以检查exception和warning的信息,当且仅当正确表达式匹配时,使用assertRaises()assertWarns()

  • 在测试用例的docstring中,描述每个测试的期望行为,不要加上“确保……”和“本测试用例是为了测试……”等字眼。

如果在docstring中很难描述某个ticket,把ticket number添加至句末。如

1
2
3
4
5
def test_foo():
"""
A test docstring looks like this (#123456).
"""
...

Imports

  • 使用 isort 自动调整引用顺序。

使用方法

1
2
$ pip install isort
$ isort -rc .

无须isort自动调整顺序的引用后添加个标记,用法如下:

1
import module  # isort:skip

  • import按如下顺序归组拜访:future,标准库,第三方库,其他Django组件,本地Django组件,try/excepts语句。每一组的import按字母表顺序。将每组的import module语句放在from module import objects之前。其他django模块的引用用绝对路径,本地模块用相对路径引用。

  • 每一行中,小写字母放在大写字母之后。

  • 使用括号和缩进来分割长行,在最后一个import后加一个逗号,右括号也放在这行上。

不同的import分组之间用一个空行,import语句和函数代码之间用两个空行

示例如下(注释仅做说明)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 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:
# ...

  • 尽可能使用简单的import

模板文件

  • 在django的模板文件中,花括号和tag中放一个空格。

推荐:

1
{{ foo }}

不推荐:

1
{{foo}}

视图文件

视图函数的第一个参数是request,不要简化为req

推荐:

1
2
def my_view(request, foo):
# ...

不推荐:

1
2
def my_view(req, foo):
# ...

模型风格

  • feild命名时,全用小写字母,用下划线连接,不要使用驼峰命名法。

推荐:

1
2
3
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)

不推荐:

1
2
3
class Person(models.Model):
FirstName = models.CharField(max_length=20)
Last_Name = models.CharField(max_length=40)

  • class Meta应当在所有的field之后,用一个空行分隔。

推荐:

1
2
3
4
5
6
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)

class Meta:
verbose_name_plural = 'people'

不推荐:

1
2
3
4
5
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)
class Meta:
verbose_name_plural = 'people'

不推荐:

1
2
3
4
5
6
class Person(models.Model):
class Meta:
verbose_name_plural = 'people'

first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)

  • model内置class和标准方法的顺序如下:
  • 所有数据库的fields的定义
  • Custom manager attributes
  • class Meta
  • def __str__()
  • def save()
  • def get_absolute_url()
  • Any custom methods
  • 要为某个域定义choices,使用tuple和大写字母,如下
    1
    2
    3
    4
    5
    6
    7
    class MyModel(models.Model):
    DIRECTION_UP = 'U'
    DIRECTION_DOWN = 'D'
    DIRECTION_CHOICES = (
    (DIRECTION_UP, 'Up'),
    (DIRECTION_DOWN, 'Down'),
    )

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 i18n documentation 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 风格

这里

original

0%