CRUDkit fixes and changes.
This commit is contained in:
parent
9d36d600bb
commit
7ddfe084ba
5 changed files with 98 additions and 43 deletions
|
|
@ -11,26 +11,37 @@ class CRUDMixin:
|
|||
|
||||
def as_dict(self, fields: list[str] | None = None):
|
||||
"""
|
||||
Serialize mapped columns. Honors projection if either:
|
||||
- 'fields' is passed explicitly, or
|
||||
-
|
||||
Serialize the instance.
|
||||
- If 'fields' (possibly dotted) is provided, emit exactly those keys.
|
||||
- Else, if '__crudkit_projection__' is set on the instance, emit those keys.
|
||||
- Else, fall back to all mapped columns on this class hierarchy.
|
||||
Always includes 'id' when present unless explicitly excluded.
|
||||
"""
|
||||
allowed = None
|
||||
if fields is None:
|
||||
fields = getattr(self, "__crudkit_projection__", None)
|
||||
|
||||
if fields:
|
||||
allowed = set(fields)
|
||||
else:
|
||||
allowed = getattr(self, "__crudkit_root_fields__", None)
|
||||
out = {}
|
||||
if "id" not in fields and hasattr(self, "id"):
|
||||
out["id"] = getattr(self, "id")
|
||||
for f in fields:
|
||||
cur = self
|
||||
for part in f.split("."):
|
||||
if cur is None:
|
||||
break
|
||||
cur = getattr(cur, part, None)
|
||||
out[f] = cur
|
||||
return out
|
||||
|
||||
result = {}
|
||||
for cls in self.__class__.__mro__:
|
||||
if not hasattr(cls, "__table__"):
|
||||
continue
|
||||
for column in cls.__table__.columns:
|
||||
name = column.name
|
||||
if allowed is not None and name not in allowed and name != "id":
|
||||
continue
|
||||
result[name] = getattr(self, name)
|
||||
for cls in self.__clas__.__mro__:
|
||||
if hasattr(cls, "__table__"):
|
||||
for column in cls.__table__.columns:
|
||||
name = column.name
|
||||
result[name] = getattr(self, name)
|
||||
return result
|
||||
|
||||
|
||||
class Version(Base):
|
||||
__tablename__ = "versions"
|
||||
|
||||
|
|
|
|||
|
|
@ -81,8 +81,8 @@ class CRUDService(Generic[T]):
|
|||
for eager in spec.get_eager_loads(root_alias, fields_map=rel_field_names):
|
||||
query = query.options(eager)
|
||||
|
||||
if root_fields or rel_field_names:
|
||||
query = query.options(Load(root_alias).raiseload("*"))
|
||||
# if root_fields or rel_field_names:
|
||||
# query = query.options(Load(root_alias).raiseload("*"))
|
||||
|
||||
if filters:
|
||||
query = query.filter(*filters)
|
||||
|
|
@ -98,26 +98,43 @@ class CRUDService(Generic[T]):
|
|||
# Only apply offset/limit when not None.
|
||||
if offset is not None and offset != 0:
|
||||
query = query.offset(offset)
|
||||
if limit is not None:
|
||||
if limit is not None and limit > 0:
|
||||
query = query.limit(limit)
|
||||
|
||||
# return query.all()
|
||||
rows = query.all()
|
||||
|
||||
try:
|
||||
rf_names = [c.key for c in (root_fields or [])]
|
||||
except NameError:
|
||||
rf_names = []
|
||||
if rf_names:
|
||||
allow = set(rf_names)
|
||||
if "id" not in allow and hasattr(self.model, "id"):
|
||||
allow.add("id")
|
||||
proj = []
|
||||
if root_fields:
|
||||
proj.extend(c.key for c in root_fields)
|
||||
for path, names in (rel_field_names or {}).items():
|
||||
prefix = ".".join(path)
|
||||
for n in names:
|
||||
proj.append(f"{prefix}.{n}")
|
||||
|
||||
if proj and "id" not in proj and hasattr(self.model, "id"):
|
||||
proj.insert(0, "id")
|
||||
|
||||
if proj:
|
||||
for obj in rows:
|
||||
try:
|
||||
setattr(obj, "__crudkit_root_fields__", allow)
|
||||
setattr(obj, "__crudkit_projection__", tuple(proj))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# try:
|
||||
# rf_names = [c.key for c in (root_fields or [])]
|
||||
# except NameError:
|
||||
# rf_names = []
|
||||
# if rf_names:
|
||||
# allow = set(rf_names)
|
||||
# if "id" not in allow and hasattr(self.model, "id"):
|
||||
# allow.add("id")
|
||||
# for obj in rows:
|
||||
# try:
|
||||
# setattr(obj, "__crudkit_root_fields__", allow)
|
||||
# except Exception:
|
||||
# pass
|
||||
|
||||
return rows
|
||||
|
||||
def create(self, data: dict, actor=None) -> T:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue