From 89f0dc6901ec62447579f701e448a8c4589d1030 Mon Sep 17 00:00:00 2001 From: mrtedn21 Date: Thu, 26 Oct 2023 13:44:06 +0700 Subject: [PATCH] fix bug with query params. now any query params can be passed before this commit exactly one param could be passed --- database.py | 2 +- http_utils.py | 24 +++++++++++++++--------- main.py | 32 ++++++++++++++++++++++++++------ users/controllers.py | 2 +- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/database.py b/database.py index 3bbc98d..eb4aaa8 100644 --- a/database.py +++ b/database.py @@ -32,7 +32,7 @@ class Base(AsyncAttrs, DeclarativeBase): def query_params_to_alchemy_filters(filters, query_param, value): - """Example of query_param: + """Example of query_param argument from url: user__first_name__like=martin""" model_name, field_name, method_name = query_param.split('__') diff --git a/http_utils.py b/http_utils.py index 6966987..cf18460 100644 --- a/http_utils.py +++ b/http_utils.py @@ -36,23 +36,29 @@ def _get_method_name(self) -> str: first_word = first_line.split(' ')[0] return first_word - def _get_path_and_query_params(self): + def _get_path_and_query_params(self) -> tuple[str, Optional[str]]: first_line = self.lines_of_header[0] second_word = first_line.split(' ')[1] - return second_word.split('?') + result = second_word.split('?') + if len(result) == 1: + path = result[0] + return path, None + else: + path, query_params = result + return path, query_params def _get_path(self): """Path is second name in first line""" - url_parts = self._get_path_and_query_params() - return url_parts[0] + path, _ = self._get_path_and_query_params() + return path - def _get_query_params(self) -> Optional[dict]: - url_parts = self._get_path_and_query_params() - if len(url_parts) == 1: - return + def _get_query_params(self) -> dict: + _, query_params_str = self._get_path_and_query_params() + if query_params_str is None: + return {} query_params = {} - for query_param in url_parts[1].split('&'): + for query_param in query_params_str.split('&'): key, value = query_param.split('=') query_params[key] = value return query_params diff --git a/main.py b/main.py index 33d108d..4b41ac5 100644 --- a/main.py +++ b/main.py @@ -70,17 +70,15 @@ async def _send_response_for_options_method(self) -> None: ) self.client_socket.close() - @staticmethod async def _get_response_for_get_method( - controller: Controller, query_params: dict, + self, controller: Controller, query_params: dict, ) -> str: controller_argument_names = get_argument_names(controller) if 'query_params' in controller_argument_names: - key, value = list(query_params.items())[0] - alchemy_filters = query_params_to_alchemy_filters( - controller.query_params, key, value, + query_params = self._prepare_query_parameters( + controller, query_params, ) - response = await controller(query_params=alchemy_filters) + response = await controller(query_params) else: response = await controller() @@ -88,6 +86,28 @@ async def _get_response_for_get_method( response = json.dumps(response) return response + @staticmethod + def _prepare_query_parameters( + controller: Controller, query_params: dict, + ) -> list: + """If request contains query parameters, then this method + returns list of translated query params to sqlalchemy filters. + But if query params is empty, this method returns [True] + that means, no filter and return all data. + + But anyway, filters must be list. In this case, user, in + controllers can use *filters and python correctly fill filters""" + if query_params: + alchemy_filters = [] + for query_name, query_value in query_params.items(): + new_filter = query_params_to_alchemy_filters( + controller.query_params, query_name, query_value, + ) + alchemy_filters.append(new_filter) + return alchemy_filters + else: + return [True] + async def _get_response_for_post_method( self, controller: Controller, http_body: str, ) -> str: diff --git a/users/controllers.py b/users/controllers.py index b2a277b..adbd214 100644 --- a/users/controllers.py +++ b/users/controllers.py @@ -30,7 +30,7 @@ async def get_users(query_params) -> str: ).select_from(UserOrm) .outerjoin(CityOrm).outerjoin(CountryOrm) .outerjoin(LanguageOrm).outerjoin(GenderOrm) - .filter(query_params) + .filter(*query_params) ) result = await session.execute(sql_query) return user_list_get_schema.dumps(map(itemgetter(0), result.fetchall()))