Django之代码风格

1 代码风格

稍微关注一下下面这些代码标准风格指导规则将会对你大有益处,咱们高度建议你通读词章,即使你此时可能正想跳过它。javascript

1.1 让你的代码保持可读性的重要性

代码在读方面的重要性赛过写。一个代码块几分钟编写,花几个小时调试,而后有可能不再会有人去碰它。然而当你去阅读那些昨天或者甚至10年之前编写的代码,清晰一致的代码风格就变得很是有用。清晰移动的代码可以让你不用去费劲去理解代码的不一致性,从而节省了本身的脑力,而且使代码易于维护,提升了各类规模项目的总体质量。css

下面这些方法让你"多走一千米"使你的代码尽量清晰易读:html

  • 避免缩写的变量名称
  • 写出你的函数的参数名称
  • 对你的类和方法要写注释文档
  • 要对你的代码加注释
  • 把重复的代码重构为可复用的函数和方法
  • 使函数和方法短一点,一个好的经验法则是读函数和方法代码时不须要滚动鼠标(也就是函数或方法的长度不能大于一个屏幕的显示高度)

当你长时间不碰某段代码后,再从新拿起这段代码,你能很容易地找到当初是从哪儿中断编写工做的html5

缩写变量名是很是使人讨厌的。好比:当你看到一个balance_sheet decrease的变量名时,解释它确定要比解释缩写版的bsd或者bal_s_d要容易。这种类型的缩写可能会帮你省一点输入时间,可是这种节省是以几小时甚至几天的技术(代码阅读)债为代价,因此这种节省不值当。java

1.2 PEP8

PEP8是一个官方的Python代码风格指南。咱们建议详细认真地阅读它并学会遵照PEP8的代码约定:(http://www.python.org/dev/peps/pep-0008/)node

PEP8描述了相似下面这样的代码约定:python

  • “每一级代码缩进使用4个空格”
  • “独立的顶级函数或者类定义语句下面必须有2个空行”
  • “类中的方法定义之间必须用一个空行隔开”

在Django项目中的全部python代码文件必须遵照PEP8。若是你记不住PEP8的代码规则,你能够为你的代码编辑器找一个检查你输入代码是否符合PEP8的插件。git

当一个有经验的Python程序员在Django项目中看到对PEP8规范的严重违反,即使他当时什么也不说,也在想这是一件很坏的事情。关于这一点,必定要相信咱们。程序员

警告:不要改变现存项目的代码约定angularjs

PEP8的代码规范通常仅对新的Django项目产生约束,若是你新参与一个项目,这个项目使用的代码约定和PEP8规范不一样,那你就遵照项目目前的代码约定便可。

请阅读PEP8规范的第8章节:愚蠢的一致性是使人讨厌的想法,这个规则正好适用于咱们此时不死守PEP8规范的状况:

**构建技巧:使用flake8检查代码质量

flake8这个项目由Tarek Ziadé发起,由PyCQA小组维护,这是一个很是有用的检查项目代码风格、质量和逻辑错误的命令行工具。当你在本地开发时,能够把它做为持续集成的一个工具组件使用。

1.2.1 79字符限制

这不是开玩笑,我仍旧把命令行控制台控制在80个字符宽度

--- Barry Morrison:系统工程师兼本书每个版本的审阅者

根据PEP8规范,每行的文本长度限制是79个字符。这样设计是由于79在文本环绕编辑器里面比较安全,开发团队在无需代码可读性的前提下即可以适应。

而后PEP8也提供一个弹性措施:能够为专属团队项目把这个限制提到99个字符。咱们理解这个所谓的专属团队项目也就是非开源项目。

下面是咱们的偏好设定:

  • 一个开源项目的行字符数必须硬性限制在79个字符之内,咱们的经验已经证实:开源项目的代码贡献者和访问者会对代码行长度这个问题有抱怨。
  • 在私有项目上,咱们把代码行长度限制放宽到99个字符,充分利用现代的显示器。

请阅读:(http://www.python.org/dev/peps/pep-0008/#maximum-line-length)

提示:Aymeric Augustin关于代码行长度问题的观点

Django核心开发者Aymeric Augustin曾说:"把代码行长度限制在79个字符这个限制,不是给变量、函数、类起糟糕名字的合理理由。给变量起一个可读性的名字比遵照几十年之前的硬件限制而引发的约束更重要。"

1.3 关于import语句的代码规范

PEP8规范建议import语句必须下面的规则排序分组:

  1. 标准库导入
  2. 相关的第三方库导入
  3. 本地应用或者特定库的导入

打咱们开发一个Django项目时,import语句应该像下面例子这样

Example1.1

# Stdlib imports
from __future__ import absolute_import
from math import sqrt
from os.path import abspath

# Core Django imports
from django.db import models
from django.utils.translation import ugettext_lazy as _

# Third-party app imports
from django_extensions.db.models import TimeStampedModel

# Imports from your apps
from splits.models import BananaSplit

(注意:你在实际项目中不须要像上面这个例子这样注释import语句,此处的注释只是为了说明例子演示的规则)

Django项目中import语句的顺序是:

  1. 标准库导入
  2. 导入Django内建资源
  3. 从第三方App的导入,包括那些与Django没有关系的App
  4. 从Django项目所建App的导入(你将在第四章读到Django App相关的内容,第四章的主题是App设计基础)

1.4 使用显式相对路径导入

当你写代码时,使用显式相对路径导入这是很重要,由于这样可让你便于移动、重命名、版本化你的模块包。在Python编程中,使用显式相对路径导入能够减小你的模块包的硬代码量要求,能够把模块包从它紧密依赖的架构环境中独立出来。由于Django App也是包的形式,因此个编码规则也适用于Django App编程。

为了演示显式相对路径导入方式的益处,让咱们看一个例子:

假定下面的代码片断摘自一个冰激凌消费量跟踪Django项目,其中消费的冰激凌品类包括大家曾经吃过的华夫、甜筒、暴风雪。

哦,不,你的cones Django App里面有全路径硬编码导入,这太糟了:

Bad Example 1.1 
# cones/views.py
from django.views.generic import CreateView
# DON'T DO THIS!
# Hardcoding of the 'cones' package
# with implicit relative imports
from cones.models import WaffleCone 
from cones.forms import WaffleConeForm 
from core.views import FoodMixin

class WaffleConeCreateView(FoodMixin, CreateView):
    model = WaffleCone
    form_class = WaffleConeForm

确实,你的cones App在你的冰激凌消费量跟踪项目里面能够正确执行,可是它里面的那些硬编码导入会使它自己的可移植性和可复用性很是差:

  • >若是你想在另一个跟踪通用甜食的Django项目中复用你的cones App,而同时却由于命名冲突不得不修改App的名字,你会怎样作?
  • >若是你有时候只是简单想改App的名字,那怎么作?

若是硬编码绝对路径导入,你在修改时就不能只改App的名字,而是不得不找到全部的此类导入并所有修改。虽然手工修改他们不难,但在你驳回相对路径导入这个办法前,请想一想与那些带有各类各样的附加功能模块的App相比,上面这个例子是很是简单的。

如今让咱们把上面这个硬编码绝对路径导入的代码片断改形成相对路径导入的好代码,下面是修正后的例子:

Example 1.2
# cones/views.py
from __future__ import absolute_import
from django.views.generic import CreateView

# Relative imports of the 'cones' package
from .models import WaffleCone
from .forms import WaffleConeForm
from core.views import FoodMixin

class WaffleConeCreateView(FoodMixin, CreateView):
    model = WaffleCone
    form_class = WaffleConeForm

另一个具体的优点是咱们能够当即辨别出本地导入和全局导入,强调Python包是一个代码单元这一点。


提示:"from future import absolute_import"语句的使用

Python3以一种更好的方式更新和改进了import语句运行机制。幸运的是:咱们可使用from __future__ import absolute_import这条语句作到对Python2.7向后兼容。即便你不计划使用Python3,可是考虑到下面表中的相对路径导入,这也是一个很棒的方法。


总结一下,下面的表格给出了不一样的Python导入类型以及在Django项目中什么时候使用它们。

导入代码 导入类型 使用场景
from core.views import FoodMixin 绝对路径导入 从目前App外部导入
from .models import WaffleCone 显式相对路径导入 从目前App的另外一个模块导入
from models import WaffleCone 隐式相对路径导入 从目前App的另外一个模块导入,但不推荐这么作

表格 1.1 导入类型 绝对路径导入 VS 显式相对路径导入 VS 隐式相对路径导入

养成使用显式相对路径导入的习惯,这很是容易作到,并且这也是一个Python程序员开发好习惯。


提示:PEP328规范不和PEP8规范冲突吗?

请看Python创始人吉多·范罗苏姆是怎么说的:


相关阅读: http://www.python.org/dev/peps/pep-0328/

1.5 避免使用import *

在咱们全部工做中的99%的状况下,咱们都应该显式导入每一个模块:

Example 1.3

from django import forms 
from django.db import models

不要写下面这样的代码:

Bad Example 1.2
# ANTI-PATTERN: Don't do this! 
from django.forms import * 
from django.db.models import *

不这样作的缘由是避免银式导入另一个python模块的内部变量而致使覆盖目前模块命名空间内的变量,那样会致使不可预知的结果,有时甚至是灾难性的结果。

咱们将在本书内容中讲解一个此规则的例外状况,这个例子将在第五章(章名之后再译)中出现。

咱们再来看一下上面的反面案例,在Django models库模块和Django forms库模块中都有一个叫CharField的类,models库中的类会覆盖掉forms库中的同名类,这种状况也会发如今Python内建库和其余第三方库之间,那样就会致使关键功能特性对象被覆盖。


警告:Python命名冲突 假如你试图导入两个具备相同命名的对象时,也会发生相同的类似的命名覆盖问题

Bad Example 1.3
# ANTI-PATTERN: Don't do this! 
from django.forms import CharField 
from django.db.models import CharField

使用import *方式,就像一个贪婪的客人进入冰激凌店后试品了全部三十一种口味冰激凌,最后却只买了1到2个球。若是你只使用模块中1到2个对象,就不要试图导入模块中全部的对象引用。

固然若是客人走出冰激凌店的时候捧着一个巨大的冰激凌碗,而里面盛着几乎全部口味的冰激凌球,固然,这是另一回事了。

1.6 Django代码风格

这一节内容将会覆盖Django官方代码约定规范以及非官方可是广泛被接受的代码规范

1.6.1 考虑一下Django代码风格指南

不用说,熟悉通用Django风格约定是个好作法。实际上,Django内部有它本身的代码风格指南,这个指南基于PEP8扩展而成。

另外,若是有内容不在官方代码标准里面明确指明,那在Django社区也会有很是常见的此类代码风格约定能够供你在项目中使用。

1.6.2 在ULR模式名称定义里使用下划线而不是破折号(中划线)

咱们平常使用下划线(字符"-")而不是破折号(字符"-"),这样作不只仅是由于更Pythonic,并且对更多的IDE和文本编辑器也更友好。注意咱们这里下面例子里说的是url()函数的name参数的值,而不是浏览器里面实际输入的URL片断(译注:正则表达式那段)。

像下面这样在url名称里面用中划线是错误的方式:

Bad Example 1.4
patterns = [
    url(regex='^add/$',
        view=views.add_topping,
        name='add-topping'),
    ]

正确的方式,是在url名称里面用下划线:

Example 1.4
patterns = [
    url(regex='^add/$',
        view=views.add_topping,
        name='add_topping'),
    ]

注意:咱们这里指的是url函数name参数的值,不是浏览器实际输入的URL片断,在URL片断里面用中划线是能够的,(好比:regex='^add-topping/$')。

1.6.3 在模板block名称里面用下划线,而不是中划线

与在URL模式名称里面用下划线同样的缘由,咱们建议在定义模板block时也使用下环线:这样的话就能够更Pythonic且对编辑器更友好。

1.7 选择JavaScript、HTML和CSS的代码风格指南

1.7.1 JavaScript代码风格指南

不像Python有官方的代码风格指南,JavaScript不存在官方代码风格指南,相代替的是,有不少我的或公司编纂的的javascript非官方代码风格指南:

在Django或JavaScript社区对于上面的代码风格指南都没有一致的意见,你只须要选择你偏好的并坚持它便可。

固然,若是你使用一个自带代码风格约定的JavaScript框架,你就应该使用它自带的代码约定。好比ember.js就有其自带的代码约定。


包提示:JSCS代码风格审查器

JSCS( http://jscs.info/ ) 是一个JavaScript代码风格审查工具。它预设好几种JavaScipt代码风格指南的编码规则,包括前面列出的代码约定中的一些。有面向好几种代码文本编辑器的JSCS插件,还有面向Gulp和Grunt之类构建工具的JSCS检查任务脚本。


1.7.2 HTML和CSS代码风格指南


包提示:CSScomb

CSScomb ( http://csscomb.com/ )一个CSS代码风格格式化工具。它检查你预配置好的风格的代码一致性和CSS属性的排序规则,就像JSCS同样,CSScomb也有面向文本编辑器的插件和面向任务构建工具的插件,其中包括面向brunch这样的HTML5构建工具的版本。


1.8 不要面向IDE(或者文本编辑器)编程

某些程序员在作出关于项目的文件布局和封装实现的选择时多是基于IDE(集成开发环境)的特性来考虑,这对于那些选择不一样不一样开发工具的程序员试图来探索你的项目代码时将变得很是困难。

常常假设你身边的程序员和你采用不一样的工具,而且你的项目代码结构足够清晰易懂,以便于他们即便使用NotePad或者Nano均可以探索你的代码。

好比:深思模板标签且查看标签源码对于那些使用功能有限的IDE工具的程序员来讲是很是困难切耗时的,所以咱们使用约定的标签模块命名方式:_tags.py。

1.9 小结

这一章包括了咱们推荐的代码风格指南以及解释咱们偏好每一个技巧的缘由。

即便你不遵照咱们推荐的代码约定,也请你遵照任何一个统一的代码风格指南。有多种代码风格的项目代码是不易维护的,而且会拖慢快发速度且提升发生开发失误的可能性。

相关文章
相关标签/搜索