代码规范

377 阅读4分钟

写在前面

  • 文档是对Python基本规范(PEP8)的一些补充,代码必须满足基本规范PEP8以后,还需要满足本规范
  • 所有规范都基于一个原则:简洁高效,如果你认为自己写的不够简洁,不够高效,那么必定不符合本规范
  • STRUCTURE.md为项目结构文件,每次提交代码必须检查是否需要更新
  • 添加或者删除接口一定先修改接口文档
  • 欢迎对代码规范进行补充

Ctrl+ALt+l召唤PEP8

代码规范

接口版本管理

接口版本v1、v2...

通过接口版本管理,利于接口的重构和项目大的更新以及迁移 v1.py

path_url = "v1"
url_service = {
    "auth": path(path_url, include(api_auth.urls)),
    ...
}

v2.py

path_url = "v2"
url_service = {
    "auth": path(path_url, include(api_auth.urls)),
    ...
}

urls.py

form config.routes.v1 import url_service as v1
form config.routes.v2 import url_service as v2
urlpatterns = []
url_path = ""
if url_version == "v1":
    urlpatterns += v1
if url_version == "v2":
    urlpatterns += v2

swagger接口管理

django 2.0及以上

  • 安装
pip install django-rest-swagger
  • settings
INSTALLED_APPS = [
    ...
    'rest_framework_swagger',
]
  • view.py

class view ,"""三引号内注明接口名称。请求required中可以查看请求字段memo该字段的数据类型str和该字段的说明流水编号。响应Response给了返回数据的标准格式,view继承django-rest-frameworkAPIView可以使用self.response_result作为返回数据,标准格式为{"code": 200,"detail": "success","data": []} 自定义状态码Http Code | detail 13001例如withdrew is error

class AccountView(BetterCreateModelMixin, viewsets.GenericViewSet):
	def create(self, request, *args, **kwargs):
        """ 增加withdraw地址:
            required: memo(str):  流水编号

           Response:

               {
                  "code": 200,
                  "detail": "ok",
                  "data": {

                      }
               }

            Http Code | detail

                200     | ok
                13504   | invalid withdraw address
                13505   | not allow add user own deposit address
                13000   | param error

        """

命名规范

  • 文件名 所有文件、文件夹使用小写字母+下划线命名

  • 常量 常量命名使用全大写+下划线

  • 普通变量 小写字母+下划线必须是名词

  • 函数名 小写字母+下划线而且函数第一个单词必须是动词

  • 类 大驼峰的形式UserManagement

settings规范

将dev_settings设置.gitignore,不提交供本地开发使用 settings.py中添加

try:
    # 使用本地环境变量
    from .dev_settings import *
except ImportError:
    # 线上无dev使用正式配置
    from .local_settings import *
  • local_settings 正式配置文件,token,key,数据库连接信息等

  • dev_settings设置 开发使用本地环境

  • INSTALLED_APPS, MIDDLEWARE等变量的赋值需要分类django,application,other...

Models规范

  • model命名 类命名+Molde ,例如:AccountModel;HistoryModel

以英文名词命名,尽量简洁

  • Meta verbose_name: 中文名词,言简意赅

verbose_name_plural:同verbose_name

db_table: 项目名+Model名,格式必须为小写英文+下划线。例如:taro_account_log

  • 字段 小写英文+下划线,例如id,name,password,is_super,is_delete,create_time

verbose_name参数必须赋值,方便阅读

使用Foreign Key时,必要设置on_delete=models.CASCADE级联删除,例如:account = models.ForeignKey(AccountModel, verbose_name="name", on_delete=models.CASCADE, unique=True)

长度设置max_length=50

唯一索引unique=True

是否为空blank=True存储空字符串, null=True数据库上表现NULL,日期型(DateField、TimeField、DateTimeField)和数字型(IntegerField、DecimalField、FloatField)不能接受空字符串,则需同时设置blank=True, null=True

  • admin 后台管理站点显示字段

admin.site.site_header

admin.site.site_title

admin.site.index_title

admin_model

显示字段list_display = ['id', 'name', 'type_no', 'src', 'side', 'dev_no', 'content', 'level', 'occ_time']

支持搜索字段search_fields = ['name', 'type_no', 'src', 'side', 'dev_no', 'content', 'bit', 'level', 'occ_time']

日期排序date_hierarchy = 'occ_time'

外键默认值raw_id_fields

url规范

  • 小写英文+横杠(-)

  • 使用名词,不能使用get、post等,动词可以通过接口的method体现

  • 每个URL后面需要注释

views规范

  • 大驼峰英文+View命名
  • 规范使用methodpost delete put get 增删改查
  • 规范注释"""三引号注明view作用
  • 规范接口返回数据{"code": 200, "detail": "success", "data":[]},返回状态码放到code描述放到detail
  • 如果用到filter,django_filter的class需要写在对应app的filters.py里
class AccountView(APIView):

	def post(self, request, *args, **kwargs):
		"""创建用户
		"""
    	pass
	def delete(self, request, *args, **kwargs):
		"""删除用户
        """
    	pass
    def put(self, request, *args, **kwargs):
		"""修改用户
        """
    	pass
	def get(self, request, *args, **kwargs):
		"""查询用户
        """
    	pass
        

serializers规范

from datetime import datetime

class Comment:
    def __init__(self, email, content, created=None):
        self.email = email
        self.content = content
        self.created = created or datetime.now()

comment = Comment(email='leila@example.com', content='foo bar')
from rest_framework import serializers

class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()
  • 序列化对象
serializer = CommentSerializer(comment)
serializer.data
# {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}
from rest_framework.renderers import JSONRenderer

json = JSONRenderer().render(serializer.data)
json
# b'{"email":"leila@example.com","content":"foo bar","created":"2016-01-27T15:17:10.375877"}'
  • 反序列化对象
import io
from rest_framework.parsers import JSONParser

stream = io.BytesIO(json)
data = JSONParser().parse(stream)
serializer = CommentSerializer(data=data)
serializer.is_valid()
# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}
  • 保存实例
class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

    def create(self, validated_data):
        return Comment(**validated_data)

    def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        return instance

import规范

  • 将import都放在头部
  • 分行书写
# yes
import os
import sys

# no
import sys,os

# yes
from subprocess import Popen, PIPE
  • 避免使用相对路径. ..
# yes
from foo.bar import Bar

# no
from ..bar import Bar

CMS规范

  • 接口统一在cms/api下,避免使用非管理平台的script、serializers和filter.

工具推荐