python
August 24, 2021
Обновленческое
Версия 0.1.5. Добавил класс PydanticHandler для поддержки POST-запросов в формате датаклассов pydantic.
Подобности тут: https://github.com/vlakir/cleanapi
Добавил в свой текущий проект. Объем кода api-сервера сократился раза в 3.
Было:
from cleanapi.server import BaseHandler from app_logger import get_logger from utils import process_error import json import pydantic from asgiref.sync import sync_to_async from tornado.web import RequestHandler from abc import ABC from common_dicts import * from common_dataclasses import FramesRequest, FramesResult from module_db.db_core import WorkDatabase from utils import get_config_setting from common_dicts import is_token_valid url_tail = '/api/v1/frames.json' logger = get_logger(__name__) print_benchmark = get_config_setting('COMMON', 'print_benchmark').lower() == 'true' class Handler(BaseHandler, RequestHandler, ABC): """ Хендлер API-запроса на список систем координат """ async def post(self): logger.info(f'Поступил входящий запрос на список систем координат') errors = [] try: body_json_dict = json.loads(self.request.body) except (json.decoder.JSONDecodeError, TypeError, ValueError) as ex: process_error('000003', errors, str(ex), logger) status_code = 400 self.set_status(status_code) self.write({'errors': errors}) return try: input_request = FramesRequest(**body_json_dict) if not is_token_valid(input_request.token): raise ValueError("Некорректный токен доступа") except pydantic.error_wrappers.ValidationError as ex: process_error('000003', errors, json.loads(ex.json()), logger) status_code = 400 self.set_status(status_code) self.write({'errors': errors}) return except ValueError as ex: process_error('000007', errors, str(ex), logger) status_code = 400 self.set_status(status_code) self.write({'errors': errors}) return try: result = await sync_to_async(_process)(input_request) except pydantic.error_wrappers.ValidationError as ex: process_error('000009', errors, json.loads(ex.json()), logger) status_code = 400 self.set_status(status_code) self.write({'errors': errors}) return except Exception as ex: process_error('000009', errors, f'{str(ex.__class__.__name__)}: {str(ex)}', logger) status_code = 400 self.set_status(status_code) self.write({'errors': errors}) return logger.info(f'Запрос на список систем координат выполнен.') if len(result.errors) == 0: result.errors = None status_code = 200 else: status_code = 400 output_json = result.json(exclude_none=True) self.set_status(status_code) self.write(output_json) # noinspection PyUnusedLocal def _process(request: FramesRequest) -> FramesResult: """ Обработчик запроса :param request: входящий запрос :type request: FramesRequest :return: результат обработки :rtype: FramesResult """ errors = [] work_database = WorkDatabase(errors, print_benchmark=print_benchmark) frames = work_database.get_all_frames(errors, print_benchmark=print_benchmark, benchmark_name='Получение справочника систем координат') result = FramesResult(frames=frames, errors=errors) return result
Стало:
from common_dataclasses import FramesRequest, FramesResult from module_db.db_core import WorkDatabase from module_frontend.app_handler import AppHandler url_tail = '/api/v1/frames.json' # noinspection PyAbstractClass class Handler(AppHandler): """ Хендлер API-запроса на список систем координат """ request_dataclass = FramesRequest result_dataclass = FramesResult # noinspection PyUnusedLocal def process(self, request: request_dataclass) -> result_dataclass: """ Обработчик запроса :param request: входящий запрос :type request: FramesRequest :return: результат обработки :rtype: FramesResult """ self.logger.info(f'Обработка запроса на {url_tail}') errors = [] work_database = WorkDatabase(errors, print_benchmark=self.print_benchmark) frames = work_database.get_all_frames(errors, print_benchmark=self.print_benchmark, benchmark_name='Получение справочника систем координат') result = FramesResult(frames=frames, errors=errors) return result
И так в каждом хэндлере, а их у меня там порядка двух десятков