response_schema.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from datetime import datetime
  4. from typing import Any
  5. from fastapi import Response
  6. from pydantic import BaseModel, ConfigDict
  7. from common.response.response_code import CustomResponse, CustomResponseCode
  8. from core.conf import settings
  9. from utils.serializers import MsgSpecJSONResponse
  10. _ExcludeData = set[int | str] | dict[int | str, Any]
  11. __all__ = ['ResponseModel', 'response_base']
  12. class ResponseModel(BaseModel):
  13. """
  14. 统一返回模型
  15. E.g. ::
  16. @router.get('/test', response_model=ResponseModel)
  17. def test():
  18. return ResponseModel(data={'test': 'test'})
  19. @router.get('/test')
  20. def test() -> ResponseModel:
  21. return ResponseModel(data={'test': 'test'})
  22. @router.get('/test')
  23. def test() -> ResponseModel:
  24. res = CustomResponseCode.HTTP_200
  25. return ResponseModel(code=res.code, msg=res.msg, data={'test': 'test'})
  26. """
  27. # TODO: json_encoders 配置失效: https://github.com/tiangolo/fastapi/discussions/10252
  28. model_config = ConfigDict(json_encoders={datetime: lambda x: x.strftime(settings.DATETIME_FORMAT)})
  29. code: int = CustomResponseCode.HTTP_200.code
  30. msg: str = CustomResponseCode.HTTP_200.msg
  31. data: Any | None = None
  32. class ResponseBase:
  33. """
  34. 统一返回方法
  35. .. tip::
  36. 此类中的方法将返回 ResponseModel 模型,作为一种编码风格而存在;
  37. E.g. ::
  38. @router.get('/test')
  39. def test() -> ResponseModel:
  40. return await response_base.success(data={'test': 'test'})
  41. """
  42. @staticmethod
  43. def __response(*, res: CustomResponseCode | CustomResponse = None, data: Any | None = None) -> ResponseModel:
  44. """
  45. 请求成功返回通用方法
  46. :param res: 返回信息
  47. :param data: 返回数据
  48. :return:
  49. """
  50. return ResponseModel(code=res.code, msg=res.msg, data=data)
  51. def success(
  52. self,
  53. *,
  54. res: CustomResponseCode | CustomResponse = CustomResponseCode.HTTP_200,
  55. data: Any | None = None,
  56. ) -> ResponseModel:
  57. return self.__response(res=res, data=data)
  58. def fail(
  59. self,
  60. *,
  61. res: CustomResponseCode | CustomResponse = CustomResponseCode.HTTP_400,
  62. data: Any = None,
  63. ) -> ResponseModel:
  64. return self.__response(res=res, data=data)
  65. @staticmethod
  66. def fast_success(
  67. *,
  68. res: CustomResponseCode | CustomResponse = CustomResponseCode.HTTP_200,
  69. data: Any | None = None,
  70. ) -> Response:
  71. """
  72. 此方法是为了提高接口响应速度而创建的,如果返回数据无需进行 pydantic 解析和验证,则推荐使用,相反,请不要使用!
  73. .. warning::
  74. 使用此返回方法时,不要指定接口参数 response_model,也不要在接口函数后添加箭头返回类型
  75. :param res:
  76. :param data:
  77. :return:
  78. """
  79. return MsgSpecJSONResponse({'code': res.code, 'msg': res.msg, 'data': data})
  80. response_base = ResponseBase()