目录

    本文主要约定在 Django 开发过程中,需要注意的一些事项。统一的编码风格,良好的设计理念,有利于项目的开发和维护,值得开发人员不断地研究和探讨。

    1. 编码声明

    在 Python 解释器执行代码时,需要告诉解释器代码的编码方式。Python 代码实际上是文本数据,如果代码的编码方式与解释器读取的编码方式不一致,将会因编码错误,代码无法执行。Python 2 解释器读取代码时,默认的编码方式是 ASCII,而如果在代码中出现非 ASCII 码的字符时,就会报错。这时,就需要声明 Python 代码的编码方式。

    1.1 设置解释器读取代码的编码格式

    为了统一 Python 解释器读取代码的格式,建议在代码文件头部统一添加,utf-8 的编码设置:

    # coding:utf-8
    

    禁止使用如下写法,在代码中重新设置编码方式:

    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')
    

    这种设置方式会导致两个问题:

    • 需要 ASCII 编码的字符参数无法传递
    • 中文作为字典的 key 值时,会出现诡异的程序行为,in 和 == 的比较行为不一致。

    1.2 字符串的编码格式

    在 Python 中有三种 string 类型:

    • unicode,text string,文本数据
    • str,byte string,二进制数据
    • basestring,是前两者的父类。

    Python 2 中的字符串 ‘xxx’ 表示 str,u’xxx’ 表示 unicode。Python 3 中,u’xxx’ 和 ‘xxx’ 都表示 unicode。而 b’xxx’ 在 Python 2 和 Python 3 中,均表示二进制数据。

    在 Python 2 中, __future__ 提供了 unicode_literals 模块,将当前文件中所有的字符串转化为 unicode ,以兼容 Python 3 字符编码。

    # coding:utf-8
    from __future__ import unicode_literals
    
    print type('测试')
    
    <type 'unicode'>
    

    字节存储的 str ,必须加前缀 b。例如下面这个例子,由于设置了 unicode_literals, 代码中字符串默认采用 unicode 编码,而 strftime 函数接受的是一个二进制字符串。这时,就需要显示的声明 %m月%d日 %H:%M 为二进制字符串;否则执行时,将会报错。

    # coding:utf-8
    from __future__ import unicode_literals
    
    from datetime import datetime
    
    print datetime.now().strftime(b'%m月%d日 %H:%M')
    

    2. PEP8

    2.1 命名

    • 模块名 尽量全小写,也可以使用下划线 module django_module
    • 全局变量\常量 全大写+下划线式驼峰 GLOBAL_VAR
    • 类名 首字母大写式驼峰 ClassName()
    • 函数命名 全小写+下划线驼峰 is_valid_data()
    • 局部变量 全小写+下划线式驼峰 this_is_var

    2.2 flake 8

    Flake8 是由 Python 官方发布的一款辅助检测Python 代码是否规范的工具。Flake8 包含三个工具:

    • PyFlakes 静态检查 Python 代码逻辑错误的工具。
    • Pep8 静态检查 PEP8 编码风格的工具。
    • NedBatchelder’s McCabe script 静态分析 Python 代码复杂度的工具。

    安装方式:

    pip install flake8
    

    使用:

    # 查看使用帮助文档
    flake8 -h 
    # 检查某个文件
    flake8 your.py
    your.py:1:1: E265 block comment should start with '# '
    # 检查当前目录
    flake8 ./
    

    flake8 会对代码是否有逻辑错误、是否符合 PEP8 规范、代码复杂度进行检测。更重要的是,flake8 会给出详细的提示信息,具体到行和列,并给出修改意见。

    3. 包引入

    3.1 import 顺序

    1. 标准库
    2. 第三方库
    3. 项目本身

    3.2 import 格式

    • 单独一行
    • 使用绝对路径,Python 2 缺省为相对路径导入,Python 3 缺省为绝对路径导入,建议统一使用绝对路径。绝对路径导入可以避免导入子模块覆盖掉标准库模块。__future__ 中提供了 absolute_import 模块支持。
    • 使用 import x 来导入包和模块,不要使用 import *
    • 使用 from x import y , 其中x是包前缀, y是不带前缀的模块名.
    • 使用 from x import y as z, 如果两个要导入的模块都叫做y或者y太长了.

    3.3 isort

    isort 是一个 Python 实用工具/库,用于按字母顺序对导入进行排序,并自动分割为各个部分。 它为各种编辑器提供了一个命令行 实用工具,Python 库和插件,可以快速地对所有导入进行排序。 它目前干净地支持 Python 2.7 - 3.6,但没有任何依赖关系。

    安装:

    pip install isort
    

    使用:

    # 对单个文件中的导入排序
    isort you.py
    # 对整个目录进行导入排序
    isort ./
    

    4. models 内部定义顺序

    • 数据库字段
    • 非数据库字段
    • 默认 objects 管理器
    • 自定义管理器属性(即其他 managers
    • class Meta
    • def natural_key() (因为它与模型紧密相关)
    • 所有 @cached_property 属性
    • 任何 @classmethod 装饰的方法
    • def __unicode__()
    • def __str__()
    • 任何以 __ 开头的方法(例如 __init__()
    • def save()
    • def delete()
    • def get_absolute_url()
    • def get_translate_url()
    • 任何自定义方法

    这里需要说明的是在 Django admin 中显示一个对象的名字,Python 2 上是使用 __unicode__(),而在 Python 3 上是使用 __str__()。为了兼容两种写法,可以使用 python_2_unicode_compatible 装饰器。

    from django.db import models
    from django.utils.encoding import python_2_unicode_compatible
    
    @python_2_unicode_compatible
    class MyModel(models.Model):
    # ...
        def __str__(self):              # __unicode__ on Python 2
            return self.my_show_name
    

    5. Python 之禅

    Python 哲学的最好阐述,莫过于核心开发者 Tim Peters 所总结的 Python 之禅

    import this
    
    • Python 以编写优美的代码为目标
    • 代码应当明了,命名规范,风格相似
    • 代码应当简洁,不要有复杂的内部实现
    • 如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁
    • 代码应当扁平,不能有太多的嵌套
    • 代码应适当的间隔,不要奢望一行代码解决问题
    • 代码应该具有良好的可读性
    • 即使有使用特例,也不要违背这些原则
    • 精准地捕获异常,不写 except: pass 风格的代码
    • 当存在多种可能,不要尝试去猜测
    • 如果不确定,就用穷举法
    • 你不是 Python 之父,有些问题解决不了
    • 动手写代码之前要思考清楚方案
    • 如果不能清楚地向他人描述实现,那么这肯定不是好的方案
    • 好好利用命名空间

    6. 代码提交注释

    bugfix : 线上功能 Bug 修复
    sprintfix:未上线代码修改
    minor:不重要的修改(换行,拼写错误等)
    feature :新功能说明
    improvement :已有功能优化
    documentation :新增说明文档,比如 readme.md 文件
    refactoring:代码重构
    

    7. 参考