Files
Wu Clan abcc9d2308 Add sync to async decorator support (#96)
* Add sync to async decorator support

* Update ASyncTranslator to asgiref
2023-06-06 20:13:33 +08:00

103 lines
2.8 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from datetime import datetime
from typing import Any
from asgiref.sync import sync_to_async
from pydantic import validate_arguments, BaseModel
from backend.app.utils.encoders import jsonable_encoder
_ExcludeData = set[int | str] | dict[int | str, Any]
__all__ = ['ResponseModel', 'response_base']
class ResponseModel(BaseModel):
"""
统一返回模型
.. tip::
如果你不想使用 ResponseBase 中的自定义编码器,可以使用此模型,返回数据将通过 fastapi 内部的编码器直接自动解析并返回
E.g. ::
@router.get('/test', response_model=ResponseModel)
def test():
return ResponseModel(data={'test': 'test'})
@router.get('/test')
def test() -> ResponseModel:
return ResponseModel(data={'test': 'test'})
""" # noqa: E501
code: int = 200
msg: str = 'Success'
data: Any | None = None
class Config:
json_encoders = {datetime: lambda x: x.strftime('%Y-%m-%d %H:%M:%S')}
class ResponseBase:
"""
统一返回方法
.. tip::
此类中的返回方法将通过自定义编码器预解析,然后由 fastapi 内部的编码器再次处理并返回,可能存在性能损耗,取决于个人喜好
E.g. ::
@router.get('/test')
def test():
return await response_base.success(data={'test': 'test'})
""" # noqa: E501
@staticmethod
@sync_to_async
def __json_encoder(data: Any, exclude: _ExcludeData | None = None, **kwargs):
custom_encoder = {datetime: lambda x: x.strftime('%Y-%m-%d %H:%M:%S')}
kwargs.update({'custom_encoder': custom_encoder})
result = jsonable_encoder(data, exclude=exclude, **kwargs)
return result
@validate_arguments
async def success(
self,
*,
code: int = 200,
msg: str = 'Success',
data: Any | None = None,
exclude: _ExcludeData | None = None,
**kwargs
) -> dict:
"""
请求成功返回通用方法
:param code: 返回状态码
:param msg: 返回信息
:param data: 返回数据
:param exclude: 排除返回数据(data)字段
:return:
"""
data = data if data is None else await self.__json_encoder(data, exclude, **kwargs)
return {'code': code, 'msg': msg, 'data': data}
@validate_arguments
async def fail(
self,
*,
code: int = 400,
msg: str = 'Bad Request',
data: Any = None,
exclude: _ExcludeData | None = None,
**kwargs
) -> dict:
data = data if data is None else await self.__json_encoder(data, exclude, **kwargs)
return {'code': code, 'msg': msg, 'data': data}
response_base = ResponseBase()