Add crudkit!
This commit is contained in:
parent
30ec29d497
commit
559fd56f33
28 changed files with 881 additions and 23 deletions
42
crudkit/eager.py
Normal file
42
crudkit/eager.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
from typing import List
|
||||
from sqlalchemy.inspection import inspect
|
||||
from sqlalchemy.orm import Load, joinedload, selectinload
|
||||
|
||||
def default_eager_policy(Model, expand: List[str]) -> List[Load]:
|
||||
"""
|
||||
Heuristic:
|
||||
- many-to-one / one-to-one: joinedload
|
||||
- one-to-many / many-to-many: selectinload
|
||||
Accepts dotted paths like "author.publisher".
|
||||
"""
|
||||
if not expand:
|
||||
return []
|
||||
|
||||
opts: List[Load] = []
|
||||
|
||||
for path in expand:
|
||||
parts = path.split(".")
|
||||
current_model = Model
|
||||
current_inspect = inspect(current_model)
|
||||
|
||||
# first hop
|
||||
rel = current_inspect.relationships.get(parts[0])
|
||||
if not rel:
|
||||
continue # silently skip bad names
|
||||
attr = getattr(current_model, parts[0])
|
||||
loader: Load = selectinload(attr) if rel.uselist else joinedload(attr)
|
||||
current_model = rel.mapper.class_
|
||||
|
||||
# nested hops, if any
|
||||
for name in parts[1:]:
|
||||
current_inspect = inspect(current_model)
|
||||
rel = current_inspect.relationships.get(name)
|
||||
if not rel:
|
||||
break
|
||||
attr = getattr(current_model, name)
|
||||
loader = loader.selectinload(attr) if rel.uselist else loader.joinedload(attr)
|
||||
current_model = rel.mapper.class_
|
||||
|
||||
opts.append(loader)
|
||||
|
||||
return opts
|
||||
Loading…
Add table
Add a link
Reference in a new issue