python后端框架相关内容
1.简介
下面以django为例,介绍比较完整的后端框架应该完成的工作
日常大部分接口主要需要考虑实现的是5,6,7步,主要需要实现的内容为
- 异常处理
- 参数校验
- 接口逻辑处理
- 数据库操作
其他我们需要思考的还有路由,view层,service层,model层,这些基本上结构都是由文件夹结构来分层次,一般按app分,下面是一个例子:
project:
apps:
test1:
services:
test1_service.py
views:
test_view.py
apps.py
dao.py
forms.py
models.py
serilizers.py
urls.py
project:
asgi.py
setting.py
urls.py
wsgi.py
tools:
api_req.py
api_req_code.py
base_error.py
validator_utils.py
一个接口的例子如下:
class Test1View(APIView):
@api_req_param(form=forms.Test1GetSerializer)
def get(self, request):
req_data = request.req_data
service = Test1Service()
res = service.get_spend_time()
return {'a': req_data.get('a', None), 'b': req_data['b'], 'res': res}
Test1GetSerializer
实现如下:
class Test1GetSerializer(CleanSerializer):
a = serializers.CharField(required=False, min_length=3)
b = serializers.EmailField(required=True, validators=[CleanValidator(key='str_prefix', prefix='abc')])
api_req_param
实现包含异常处理和参数校验,异常处理在最顶层,代码如下:
def api_req_param(req_data='GET', form=serializers.Serializer):
def api_req_param_decorator(func):
_post_code2 = get_post_code2(inspect.getsourcefile(func))
@api_req(_post_code2)
@api_param(req_data=req_data, form=form)
@wraps(func)
def wrapped_func(*args, **kwargs):
return func(*args, **kwargs)
return wrapped_func
return api_req_param_decorator
2.异常处理
异常处理放置在最顶层的好处是能捕获全局所有异常,代码中可以用raise XXX的形式来随时中断程序抛出异常
关于异常处理重点包含:
- 异常码定义
- 各种异常定义
异常处理代码如下:
def api_req(post_code2=None):
def api_req_decorator(func):
@wraps(func)
def wrapped_func(self, request, *args, **kwargs):
self.post_code2 = model_code_dict.get(post_code2, 'XX')
err_resp = ErrResponse(self.post_code2)
try:
res = func(self, request, *args, **kwargs)
return Response({'code': '0000', 'data': res, 'message': 'success'})
except BaseError as base_e:
return Response(err_resp.get_err_res(base_e.code1, base_e.message, base_e.code3))
except Exception as e:
return Response(err_resp.get_err_res('X', str(e), 'X'))
return wrapped_func
return api_req_decorator
class ErrResponse:
def __init__(self, post_code2='XX'):
self.post_code2 = post_code2
def get_err_res(self, code1='X', message='', code3='0'):
return {'code': code1 + self.post_code2 + code3, 'data': {}, 'message': message}
2.1.异常码定义
关于异常码这里只举一个例子:
- 四位构成
- code1:第一位为异常分类,比如参数校验异常,数据库连接异常等
- code2:第二位和第三位定义异常模块,说明这个异常出自哪个模块
- code3:第四位为异常详情
- message:除了异常码同时还有一个异常详情
message
字段说明异常详情
code1_dict = {
'OK': ('0', 'success'),
'ErrorParam': ('1', 'input param is wrong')
}
model_code_dict = {'apps.test1': '00'}
code2由程序自动获取,代码如下:
def get_post_code2(path):
path = path.replace('\\', '/')
path_l = path.split('/apps/')
if len(path_l) == 1:
return None
i = path_l[1].find('/')
path = 'apps.' + path_l[1][:i] + '.apps'
module = importlib.import_module(path)
for name, cls in inspect.getmembers(module, inspect.isclass):
post_code2 = getattr(cls, 'name', None)
if post_code2 is not None:
return post_code2
return None
2.2.异常定义
代码如下:
class BaseError(Exception):
def __init__(self, message, code1='unknown', code3='0'):
self.message = message
if code1_dict.get(code1, None) is None:
self.code1 = 'X'
else:
self.code1 = code1_dict[code1][0]
self.code3 = code3
class ParamError(BaseError):
def __init__(self, message, code3='0'):
super().__init__(message, 'ErrorParam', code3)
3.参数校验
代码如下:
def api_param(req_data='GET', form=serializers.Serializer):
def api_param_decorator(func):
@wraps(func)
def wrapped_func(self, request, *args, **kwargs):
try:
data = form(data=getattr(request, req_data))
data.is_valid(raise_exception=True)
except Exception as e:
logging.getLogger(__name__).error(f'parameter error {e!s}')
raise ParamError(str(e))
request.req_data = data.data
return func(self, request, *args, **kwargs)
return wrapped_func
return api_param_decorator
除了全局校验可以自定义校验类:
class CleanValidator:
code = 'invalid'
def __init__(self, key, *args, **kwargs):
self.key = key
self.args = args
self.kwargs = kwargs
@staticmethod
def clean_str_prefix(value, prefix=''):
if not value.startswith(prefix):
raise ValidationError(f'{value!s}\'s prefix should equal {prefix!s}')
def __call__(self, value):
handler = getattr(self, 'clean_' + self.key, None)
if handler is None:
raise ValidationError(f'you need achieve your method about {self.key}', code=self.code)
return handler(value, *self.args, **self.kwargs)
class CleanSerializer(serializers.Serializer):
def create(self, validated_data):
pass
def update(self, instance, validated_data):
pass
4.接口逻辑处理
接口逻辑具体实现在service中:
class Test1Service:
def __init__(self):
self.start_time = time()
def get_spend_time(self):
return time() - self.start_time
5.数据库操作
数据库操作可以统一放在dao.py中,或者如果数据库操作已经封装得比较好了(ORM),也可以考虑放在service中