More attempts to fix a bug.
This commit is contained in:
parent
bd2daf921a
commit
dd863dba99
3 changed files with 102 additions and 21 deletions
|
|
@ -145,16 +145,18 @@ def _split_field_tokens(fields: Iterable[str]) -> Tuple[List[str], Dict[str, Lis
|
|||
def _deep_get_loaded(obj: Any, dotted: str) -> Any:
|
||||
"""
|
||||
Deep get with no lazy loads:
|
||||
- Walk intermediate hops via _safe_get_loaded_attr only.
|
||||
- Final hop: prefer _safe_get_loaded_attr; if that returns an ORM object or a collection of ORM objects,
|
||||
serialize to simple dicts; else return the plain value.
|
||||
- Intermediate hops via _safe_get_loaded_attr only.
|
||||
- Final hop:
|
||||
* If relationship and not loaded: return None
|
||||
* else allow getattr for non-relationship attrs (hybrids/properties) that compute from already-loaded data.
|
||||
* Serialize ORM objects at the lead into dicts
|
||||
"""
|
||||
parts = dotted.split(".")
|
||||
if not parts:
|
||||
return None
|
||||
|
||||
cur = obj
|
||||
# Traverse up to parent of last token without lazy-loads
|
||||
# Traverse up to the parent of the last token safely
|
||||
for part in parts[:-1]:
|
||||
if cur is None:
|
||||
return None
|
||||
|
|
@ -163,24 +165,36 @@ def _deep_get_loaded(obj: Any, dotted: str) -> Any:
|
|||
return None
|
||||
|
||||
last = parts[-1]
|
||||
|
||||
# If last is an ORM relationship, only return it if already loaded.
|
||||
m = _sa_mapper(cur)
|
||||
if m is not None and last in m.relationships:
|
||||
val = _safe_get_loaded_attr(cur, last)
|
||||
if val is None:
|
||||
return None
|
||||
# serialize relationship value
|
||||
if _sa_mapper(val) is not None:
|
||||
return _serialize_simple_obj(val)
|
||||
if isinstance(val, (list, tuple)):
|
||||
out = []
|
||||
for v in val:
|
||||
out.append(_serialize_simple_obj(v) if _sa_mapper(v) is not None else v)
|
||||
return out
|
||||
return val
|
||||
|
||||
# Not a relationship: try loaded value, else safe getattr
|
||||
val = _safe_get_loaded_attr(cur, last)
|
||||
if val is None:
|
||||
# Do NOT lazy load. If it isn't loaded, treat as absent.
|
||||
return None
|
||||
try:
|
||||
# getattr here will not lazy-load relationships because we already gated those
|
||||
val = getattr(cur, last, None)
|
||||
except Exception:
|
||||
val = None
|
||||
|
||||
# If the final hop is an ORM object or collection, serialize it
|
||||
if _sa_mapper(val) is not None:
|
||||
return _serialize_simple_obj(val)
|
||||
if isinstance(val, (list, tuple)):
|
||||
out = []
|
||||
for v in val:
|
||||
if _sa_mapper(v) is not None:
|
||||
out.append(_serialize_simple_obj(v))
|
||||
else:
|
||||
out.append(v)
|
||||
return out
|
||||
|
||||
# Plain scalar/computed value
|
||||
return [_serialize_simple_obj(v) if _sa_mapper(v) is not None else v for v in val]
|
||||
return val
|
||||
|
||||
def _serialize_leaf(obj: Any) -> Any:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue