diff --git a/bmgt435_elp/apis.py b/bmgt435_elp/apis.py index 6d89ff5..050111e 100644 --- a/bmgt435_elp/apis.py +++ b/bmgt435_elp/apis.py @@ -8,7 +8,6 @@ from .simulation.Cases import FoodCenter, SimulationException from .bmgtModels import * from .utils.statusCode import Status -from .utils.jsonUtils import serialize_models, serialize_model_instance, serialize_simulation_result from .utils.apiUtils import request_error_handler, password_valid, generic_paginated_query, pager_params_from_request, create_pager_params, AppResponse import pandas as pd @@ -56,7 +55,7 @@ def sign_in(request: HttpRequest) -> AppResponse: user = BMGTUser.objects.get(did=did, activated=True,) if check_password(password, user.password): AuthApi.__set_auth_cookie(resp, user) - resp.resolve(serialize_model_instance(user)) + resp.resolve(user) else: resp.reject("Sign in failed. Please check your directory ID and password!") except BMGTUser.DoesNotExist: @@ -129,7 +128,7 @@ def me(request: HttpRequest,) -> HttpResponse: try: resp = AppResponse() user = _get_session_user(request) - resp.resolve(serialize_model_instance(user)) + resp.resolve(user) except BMGTUser.DoesNotExist: resp.reject("User not found!") except KeyError: @@ -148,7 +147,7 @@ def get_group(request: HttpRequest) -> AppResponse: resp = AppResponse() group_id = int(request.GET.get('id')) group = BMGTGroup.objects.get(id=group_id) - resp.resolve(serialize_model_instance(group)) + resp.resolve(group) except BMGTGroup.DoesNotExist: resp.reject("Group not found!") except KeyError: @@ -185,7 +184,7 @@ def join_group(request: HttpRequest) -> HttpResponse: if group.users.count() < MAX_GROUP_SIZE: user.group = group user.save() - resp.resolve(serialize_model_instance(group)) + resp.resolve(group) else: resp.reject("Group already full!") else: @@ -231,7 +230,7 @@ def get(request: HttpRequest) -> HttpResponse: resp = AppResponse() case_id = request.GET.get('case_id', None) case = BMGTCase.objects.get( id=case_id, visible=True) - resp.resolve(serialize_model_instance(case)) + resp.resolve(case) except BMGTCase.DoesNotExist: resp.reject("Case not found!") except KeyError: @@ -311,7 +310,7 @@ def get_case_record(request: HttpRequest) -> HttpResponse: resp = AppResponse() case_record_id = request.GET.get('id', None) case_record = BMGTCaseRecord.objects.get(id=case_record_id, ) - resp.resolve(serialize_model_instance(case_record)) + resp.resolve(case_record) except BMGTCaseRecord.DoesNotExist: resp.reject("Case record not found!") except KeyError: @@ -458,7 +457,7 @@ def create_semester(request: HttpRequest) -> HttpResponse: with transaction.atomic(): semester = BMGTSemester(year=year, season=season) semester.save() - resp.resolve(serialize_model_instance(semester)) + resp.resolve(semester) except IntegrityError: resp.reject("Invalid semester arguments!") @@ -489,7 +488,7 @@ def get_semesters(request: HttpRequest) -> HttpResponse: try: resp = AppResponse() semesters = BMGTSemester.objects.all() - resp.resolve(serialize_models(semesters)) + resp.resolve(semesters) except Exception as e: resp.reject(e) diff --git a/bmgt435_elp/utils/apiUtils.py b/bmgt435_elp/utils/apiUtils.py index 0593910..f5e586b 100644 --- a/bmgt435_elp/utils/apiUtils.py +++ b/bmgt435_elp/utils/apiUtils.py @@ -3,7 +3,7 @@ from django.core.paginator import Paginator, EmptyPage from django.http import HttpRequest, HttpResponse from .statusCode import Status -from .jsonUtils import serialize_paginated_data, serialize_models, CustomJSONEncoder +from .jsonUtils import CustomJSONEncoder from ..simulation.Cases import SimulationException from ..bmgtModels import BMGTTransaction @@ -145,14 +145,21 @@ def generic_paginated_query(dbModel, pager_params, **kwargs) -> HttpResponse: obj_set = obj_set.order_by( pager_params['order'] if pager_params['asc'] else '-'+pager_params['order']) pager = Paginator(obj_set, pager_params['size']) + page = pager_params['page'] - if pager_params['page'] > pager.num_pages or pager_params['page'] < 1: + if page > pager.num_pages or page < 1: resp.reject("Page not found!") else: - resp.resolve(serialize_paginated_data(pager, pager_params['page'])) + resp.resolve({ + "page": page, + "totalPage": pager.num_pages, + "data":pager.page(page).object_list, + }) except EmptyPage: resp.reject("Page empty!") + except KeyError: + resp.reject("Missing pagination parameters!") return resp diff --git a/bmgt435_elp/utils/jsonUtils.py b/bmgt435_elp/utils/jsonUtils.py index fcce81b..ab1f345 100644 --- a/bmgt435_elp/utils/jsonUtils.py +++ b/bmgt435_elp/utils/jsonUtils.py @@ -10,33 +10,30 @@ class CustomJSONEncoder(json.JSONEncoder): + typeMapper = { + datetime.datetime: lambda obj: obj.astimezone().isoformat(), + np.integer: lambda obj: int(obj), + np.floating: lambda obj: float(obj), + QuerySet: lambda obj: [model.as_dictionary() for model in obj], + list[BMGTModelBase]: lambda obj: [model.as_dictionary() for model in obj], + BMGTModelBase: lambda obj: obj.as_dictionary(), + SimulationResult: lambda obj: obj.iteration_dataframe, + } + def default(self, obj): - if isinstance(obj, datetime.datetime): - return obj.astimezone().isoformat() - elif isinstance(obj, np.integer): - return int(obj) - elif isinstance(obj, np.floating): - return float(obj) - else: - return super().default(obj) + objType = type(obj) + if issubclass(objType, BMGTModelBase): + return self.typeMapper[BMGTModelBase](obj) + if self.typeMapper.get(objType, False): + return self.typeMapper[objType](obj) + return super().default(obj) def serialize_models(querySet:QuerySet | list[BMGTModelBase]) -> str: return json.dumps([model.as_dictionary() for model in querySet], cls=CustomJSONEncoder) - def serialize_model_instance(instance:BMGTModelBase) -> str: return json.dumps(instance.as_dictionary(), cls=CustomJSONEncoder) - -def serialize_paginated_data(paginator, pageIndex: int) -> str: - - return json.dumps({ - "page": pageIndex, - "totalPage": paginator.num_pages, - "data": json.loads(serialize_models(paginator.page(pageIndex).object_list)), - }) - - def serialize_simulation_result(result: SimulationResult) -> str: return json.dumps(result.iteration_dataframe, cls=CustomJSONEncoder)