From b12b627ba48a74241a427f06f0ae31feccd09e4c Mon Sep 17 00:00:00 2001 From: Jesus Lara Date: Wed, 19 Feb 2025 02:27:42 +0100 Subject: [PATCH 1/3] fix on returning value for json types, migrated to use json_encoder from datamodel --- examples/test_model.py | 69 ++++++++++++++++++++++++++++++++++--- navigator/navigator.py | 2 +- navigator/responses.py | 6 ++-- navigator/views/abstract.py | 5 ++- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/examples/test_model.py b/examples/test_model.py index 50823c44..4b323875 100644 --- a/examples/test_model.py +++ b/examples/test_model.py @@ -29,7 +29,7 @@ class Country(Model): country: str class Airport(Model): - iata: str = Column(primary_key=True, required=True, label='IATA Code') + iata: str = Column(primary_key=True, required=True, label='IATA Code', default='AEP') airport: str = Column(required=True, label="Airport Name") airport_type: AirportType = Column( required=True, @@ -38,17 +38,23 @@ class Airport(Model): default=AirportType.CITY ) city: str - country: str + country: str # = Column(foreign_key=Country.country) created_by: int created_at: datetime = Column(default=datetime.now(), repr=False) + def __post_init__(self): + return super().__post_init__() + + def geography(self): + return self.city, self.country + class Meta: name: str = 'airports' schema = 'public' strict = True -app = Application() +app = Application(enable_jinja2=True) session = AuthHandler() session.setup(app) @@ -62,6 +68,60 @@ class AirportHandler(ModelView): pk: Union[str, list] = ['iata'] dsn: str = dsn + async def _pre_get(self, *args, **kwargs): + print(' REQUEST ', self.request) + app = self.request.app + session = self.request.get('session') + print('SESSION ', session) + print('APP ', app) + db = app['database'] + async with await db.acquire() as conn: + query = "SELECT * FROM public.airports" + result, _ = await conn.query(query) + print(result) + template = app['template'] + auth = app['auth'] + return True + + async def _get_data(self, queryparams, args): + data = await super()._get_data(queryparams, args) + async with await self.handler(request=self.request) as conn: + # Country.Meta.connection = conn + # country = await Country.get(country=data.country) + # print(country) + query = f"SELECT * FROM public.airports WHERE iata = '{queryparams.get('iata')}'" + result, _ = await conn.queryrow(query) + if result: + print(result) + print('DATA > ', data) + print('QS ', queryparams) + return data + + async def _put_response(self, result, status = 200, fields = None): + return await super()._put_response(result, status, fields) + + async def _get_callback(self, response: web.Response, result, *args, **kwargs): + await asyncio.sleep(3) + print('GET CALLBACK', result) + return response + + async def _post_callback(self, response: web.Response, result, *args, **kwargs): + print('POST CALLBACK', result) + return response + + async def _put_callback(self, response: web.Response, result, *args, **kwargs): + print('PUT CALLBACK', result) + return response + + async def _patch_callback(self, response: web.Response, result, *args, **kwargs): + print('PATCH CALLBACK', result) + return response + + + + def required_by_put(self, *args, **kwargs): + return True + async def _set_created_by(self, value, column, **kwargs): return await self.get_userid(session=self._session) @@ -133,7 +193,7 @@ async def start_example(db): }, ] await Airport.create(data) - await db.release(conn) + # await db.release(conn) async def end_example(db): @@ -166,6 +226,7 @@ async def end_example(db): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) pool = AsyncPool("pg", params=params, loop=loop, **kwargs) + app['database'] = pool loop.run_until_complete( start_example(pool) ) diff --git a/navigator/navigator.py b/navigator/navigator.py index 1a2ac3ee..9725bca7 100644 --- a/navigator/navigator.py +++ b/navigator/navigator.py @@ -14,6 +14,7 @@ from aiohttp.abc import AbstractView from aiohttp.web_exceptions import HTTPError import sockjs +from datamodel.parsers.json import json_encoder try: from navconfig import config @@ -43,7 +44,6 @@ # websocket resources from .resources import WebSocketHandler -from .libs.json import json_encoder from .types import WebApp diff --git a/navigator/responses.py b/navigator/responses.py index 9c82abc8..fa5d5e2c 100644 --- a/navigator/responses.py +++ b/navigator/responses.py @@ -12,7 +12,7 @@ HTTPNoContent, ) from aiohttp_sse import sse_response, EventSourceResponse -from .libs.json import json_encoder +from datamodel.parsers.json import json_encoder __all__ = ( @@ -38,9 +38,9 @@ def Response( if headers: response["headers"] = headers if content and isinstance(content, str) or text is not None: - response["text"] = content if content else text + response["text"] = content or text else: - response["body"] = content if content else body + response["body"] = content or body return web.Response(**response) diff --git a/navigator/views/abstract.py b/navigator/views/abstract.py index 0ce0f2f4..909a5c80 100644 --- a/navigator/views/abstract.py +++ b/navigator/views/abstract.py @@ -514,7 +514,10 @@ async def _get_meta_info(self, meta: str, fields: list): for _, field in self.model.get_columns().items(): key = field.name _type = field.db_type() - _t = JSON_TYPES[field.type] + try: + _t = JSON_TYPES[field.type] + except KeyError: + _t = str(field.db_type()) default = None if field.default is not None: default = f"{field.default!r}" From fb182dec948650a46a0902b9e301ee4ff392e066 Mon Sep 17 00:00:00 2001 From: Jesus Lara Date: Wed, 19 Feb 2025 02:28:30 +0100 Subject: [PATCH 2/3] using datamodel json encoder with aiohttp --- navigator/views/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/navigator/views/base.py b/navigator/views/base.py index a28c5c15..2fce0842 100644 --- a/navigator/views/base.py +++ b/navigator/views/base.py @@ -34,6 +34,7 @@ # Monkey-patching DEFAULT_JSON_ENCODER = json_encoder DEFAULT_JSON_DECODER = json_decoder + # monkey-patch the JSON encoder aiohttp.typedefs.DEFAULT_JSON_ENCODER = json_encoder aiohttp.typedefs.DEFAULT_JSON_DECODER = json_decoder From 57ca65b3517811a43151988564fe009eba8b573c Mon Sep 17 00:00:00 2001 From: Jesus Lara Date: Wed, 19 Feb 2025 02:29:04 +0100 Subject: [PATCH 3/3] new version of asyncdb and datamodel --- navigator/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/navigator/version.py b/navigator/version.py index 8c9c2071..e7853e6f 100644 --- a/navigator/version.py +++ b/navigator/version.py @@ -4,7 +4,7 @@ __description__ = ( "Navigator Web Framework based on aiohttp, " "with batteries included." ) -__version__ = "2.12.12" +__version__ = "2.12.13" __copyright__ = "Copyright (c) 2020-2024 Jesus Lara" __author__ = "Jesus Lara" __author_email__ = "jesuslarag@gmail.com"