import json
from django.http import *
from .api_params import *
api_methods_dict = {}
def api_make_response(response):
return API_OK_OBJ | {"response": response}
# def api_make_param(name, arg_class, description, required=True):
# return {
# "name": name,
# "type": arg_class,
# "description": description,
# "required": required
# }
# API_PARAM_ACCESS_TOKEN = api_make_param(
# "access_token",
# AccessToken,
# "Токен, выданный методом account.auth
"
# )
def default_serializer(obj):
try:
return obj.to_json()
except Exception:
return str(obj)
def api_method(func_name, doc="", params: list or None = None, returns=""):
"""
Декоратор для методов API, автоматически валидирует и передает параметры методам
"""
def actual_decorator(func):
async def wrapper(__raw_request, **kwargs):
print(f"> call method {func_name} with params {kwargs}. method params: {params}")
errors = []
func_args = {}
for p in params:
try:
if not isinstance(p, ApiParam):
raise Exception(API_ERROR_INTERNAL_ERROR, f"param {p} is not instance of ApiParam class")
name = p.get_name()
if isinstance(p, ApiRequestParam):
func_args[name] = __raw_request
else:
value = kwargs[name] if name in kwargs else None
if asyncio.iscoroutinefunction(p.validate):
func_args[name] = await p.validate(value)
else:
func_args[name] = p.validate(value)
except Exception as ex:
errors.append(ex)
# print(f"errors: {errors}, args: {func_args}")
if len(errors) > 0:
if len(errors) == 1:
obj = make_error_object(errors[0])
else:
obj = make_error_object(errors)
response = HttpResponseBadRequest(json.dumps(obj, default=default_serializer, ensure_ascii=False, indent=4))
response.headers["Content-type"] = "application/json; charset=utf-8"
return response
else:
try:
if asyncio.iscoroutinefunction(func):
out = await func(**func_args)
else:
out = func(**func_args)
except Exception as ex:
return make_error_object(ex)
if out is None:
obj = make_error_object(Exception(API_ERROR_INTERNAL_ERROR, "method returned null object"))
response = HttpResponseServerError(json.dumps(obj, default=default_serializer, ensure_ascii=False, indent=4))
response.headers["Content-type"] = "application/json; charset=utf-8"
return response
if not isinstance(out, dict) and not isinstance(out, HttpResponse):
obj = make_error_object(Exception(API_ERROR_INTERNAL_ERROR, "method returned invalid object type"))
response = HttpResponseServerError(json.dumps(obj, default=default_serializer, ensure_ascii=False, indent=4))
response.headers["Content-type"] = "application/json; charset=utf-8"
return response
return out
api_methods_dict[func_name] = {
"doc": doc,
"params": params,
"func": wrapper,
"returns": returns
}
return wrapper
return actual_decorator