Skip to content

Commit 5d2494c

Browse files
committed
feat: add new function convert_dicts
1 parent 8241bfb commit 5d2494c

File tree

8 files changed

+55
-11
lines changed

8 files changed

+55
-11
lines changed

examples/service/routers/account.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33

44
from faker import Faker
55
from fastapi import APIRouter, Body, Query
6-
from fastapi_esql import Cases, RawSQL
6+
from fastapi_esql import Cases, Q, RawSQL
77
from pydantic import BaseModel, Field
8-
from tortoise.queryset import Q
98

109
from examples.service.constants.enums import GenderEnum, LocaleEnum
1110
from examples.service.managers.demo.account import AccountMgr
@@ -45,11 +44,20 @@ async def update_view(
4544
async def query_by_id_view(
4645
aid: int = Query(...),
4746
):
47+
meta = AccountMgr.model._meta
48+
print(dir(meta))
49+
print("db_complex_fields", meta.db_complex_fields, "", sep="\n")
50+
print("db_default_fields", meta.db_default_fields, "", sep="\n")
51+
print("db_fields", meta.db_fields, "", sep="\n")
52+
print("db_native_fields", meta.db_native_fields, "", sep="\n")
53+
print("fields_map", meta.fields_map, "", sep="\n")
4854
# account = await AccountMgr.get_by_pk(aid)
4955
account = await AccountMgr.select_one_record(
5056
fields=["*"],
5157
wheres=Q(id=aid),
58+
convert_fields=["active", "gender", "locale", "extend"],
5259
)
60+
print(account)
5361
return {"account": account}
5462

5563

fastapi_esql/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
RawSQL,
1818
SQLizer,
1919
Singleton,
20+
convert_dicts,
2021
timing,
2122
)
2223

@@ -34,6 +35,7 @@
3435
"RawSQL",
3536
"SQLizer",
3637
"Singleton",
38+
"convert_dicts",
3739
"timing",
3840
]
3941

fastapi_esql/const/error.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
class WrongParamsError(Exception):
1+
class QsParsingError(Exception):
22
...
33

44

5-
class QsParsingError(Exception):
5+
class WrongParamsError(Exception):
66
...

fastapi_esql/orm/base_manager.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ async def select_custom_fields(
6969
orders: Optional[List[str]] = None,
7070
offset: Optional[int] = None,
7171
limit: Optional[int] = None,
72+
convert_fields: Optional[List[str]] = None,
7273
conn: Optional[BaseDBAsyncClient] = None,
7374
):
7475
sql = SQLizer.select_custom_fields(
@@ -84,7 +85,11 @@ async def select_custom_fields(
8485
cls.model,
8586
)
8687
conn = conn or cls.ro_conn
87-
return await CursorHandler.fetch_dicts(sql, conn, logger)
88+
converters = {
89+
f: cls.model._meta.fields_map[f].to_python_value
90+
for f in convert_fields if f in cls.model._meta.db_fields
91+
} if convert_fields else None
92+
return await CursorHandler.fetch_dicts(sql, conn, logger, converters)
8893

8994
@classmethod
9095
async def select_one_record(
@@ -95,6 +100,7 @@ async def select_one_record(
95100
groups: Optional[List[str]] = None,
96101
having: Optional[str] = None,
97102
orders: Optional[List[str]] = None,
103+
convert_fields: Optional[List[str]] = None,
98104
conn: Optional[BaseDBAsyncClient] = None,
99105
):
100106
sql = SQLizer.select_custom_fields(
@@ -110,7 +116,11 @@ async def select_one_record(
110116
cls.model,
111117
)
112118
conn = conn or cls.ro_conn
113-
return await CursorHandler.fetch_one(sql, conn, logger)
119+
converters = {
120+
f: cls.model._meta.fields_map[f].to_python_value
121+
for f in convert_fields if f in cls.model._meta.db_fields
122+
} if convert_fields else None
123+
return await CursorHandler.fetch_one(sql, conn, logger, converters)
114124

115125
@classmethod
116126
async def update_json_field(

fastapi_esql/utils/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from .converter import convert_dicts
12
from .cursor_handler import CursorHandler
23
from .decorator import timing
34
from .metaclass import Singleton

fastapi_esql/utils/converter.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from logging import getLogger
2+
from typing import Dict, Callable
3+
4+
logger = getLogger(__name__)
5+
6+
7+
def convert_dicts(dicts, converters: Dict[str, Callable]):
8+
if not converters:
9+
return
10+
for d in dicts:
11+
for f, cvt in converters.items():
12+
v = d[f]
13+
try:
14+
d[f] = cvt(v)
15+
except Exception as e:
16+
logger.warning(f"Converting value `{v}` by `{cvt.__name__}` failed => {e}")

fastapi_esql/utils/cursor_handler.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from logging import Logger
2-
from typing import Any, Dict, List, Optional
2+
from typing import Any, Dict, List, Optional, Callable
33

44
from tortoise import BaseDBAsyncClient
55

6+
from .converter import convert_dicts
7+
68

79
class CursorHandler:
810

@@ -12,9 +14,12 @@ async def fetch_dicts(
1214
sql: str,
1315
conn: BaseDBAsyncClient,
1416
logger: Logger,
17+
converters: Dict[str, Callable] = None,
1518
) -> Optional[List[Dict[str, Any]]]:
1619
try:
17-
return await conn.execute_query_dict(sql)
20+
dicts = await conn.execute_query_dict(sql)
21+
convert_dicts(dicts, converters)
22+
return dicts
1823
except Exception as e:
1924
logger.exception(f"{e} SQL=>{sql}")
2025
return None
@@ -25,9 +30,11 @@ async def fetch_one(
2530
sql: str,
2631
conn: BaseDBAsyncClient,
2732
logger: Logger,
33+
converters: Dict[str, Callable] = None,
2834
) -> Optional[Dict[str, Any]]:
2935
try:
3036
dicts = await conn.execute_query_dict(sql)
37+
convert_dicts(dicts, converters)
3138
if dicts:
3239
return dicts[0]
3340
return {}

fastapi_esql/utils/sqlizer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def resolve_wheres(
5050
model: Optional[Model] = None,
5151
) -> str:
5252
if not model and not isinstance(wheres, str):
53-
raise WrongParamsError("Parameter `wheres` only supports str if no model exists")
53+
raise WrongParamsError("Parameter `wheres` only supports `str` if no model exists")
5454

5555
if isinstance(wheres, str):
5656
return wheres
@@ -61,10 +61,10 @@ def resolve_wheres(
6161
elif isinstance(wheres, list):
6262
qs = [q for q in wheres if isinstance(q, Q)]
6363
else:
64-
raise WrongParamsError("Parameter `wheres` only support str, Q, Dict[str, Any] and List[Q]")
64+
raise WrongParamsError("Parameter `wheres` only support `str`, `Q`, `Dict[str, Any]` and `List[Q]`")
6565

6666
if not qs:
67-
raise QsParsingError("Parsing `wheres` for QuerySet failed")
67+
raise QsParsingError("Parsing `wheres` for `QuerySet` failed")
6868

6969
modifier = QueryModifier()
7070
for q in qs:

0 commit comments

Comments
 (0)