Redesign1 #1

Merged
yaro merged 36 commits from Redesign1 into main 2025-09-22 14:12:39 -05:00
5 changed files with 64 additions and 30 deletions
Showing only changes of commit 82062d72d6 - Show all commits

View file

@ -1,5 +1,6 @@
from __future__ import annotations from __future__ import annotations
import os import os
import os
from typing import Dict, Any, Optional, Type from typing import Dict, Any, Optional, Type
from urllib.parse import quote_plus from urllib.parse import quote_plus
from pathlib import Path from pathlib import Path

View file

@ -11,26 +11,37 @@ class CRUDMixin:
def as_dict(self, fields: list[str] | None = None): def as_dict(self, fields: list[str] | None = None):
""" """
Serialize mapped columns. Honors projection if either: Serialize the instance.
- 'fields' is passed explicitly, or - 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: if fields:
allowed = set(fields) out = {}
else: if "id" not in fields and hasattr(self, "id"):
allowed = getattr(self, "__crudkit_root_fields__", None) 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 = {} result = {}
for cls in self.__class__.__mro__: for cls in self.__clas__.__mro__:
if not hasattr(cls, "__table__"): if hasattr(cls, "__table__"):
continue for column in cls.__table__.columns:
for column in cls.__table__.columns: name = column.name
name = column.name result[name] = getattr(self, name)
if allowed is not None and name not in allowed and name != "id":
continue
result[name] = getattr(self, name)
return result return result
class Version(Base): class Version(Base):
__tablename__ = "versions" __tablename__ = "versions"

View file

@ -101,23 +101,40 @@ class CRUDService(Generic[T]):
if limit is not None and limit > 0: if limit is not None and limit > 0:
query = query.limit(limit) query = query.limit(limit)
# return query.all()
rows = query.all() rows = query.all()
try: proj = []
rf_names = [c.key for c in (root_fields or [])] if root_fields:
except NameError: proj.extend(c.key for c in root_fields)
rf_names = [] for path, names in (rel_field_names or {}).items():
if rf_names: prefix = ".".join(path)
allow = set(rf_names) for n in names:
if "id" not in allow and hasattr(self.model, "id"): proj.append(f"{prefix}.{n}")
allow.add("id")
if proj and "id" not in proj and hasattr(self.model, "id"):
proj.insert(0, "id")
if proj:
for obj in rows: for obj in rows:
try: try:
setattr(obj, "__crudkit_root_fields__", allow) setattr(obj, "__crudkit_projection__", tuple(proj))
except Exception: except Exception:
pass 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 return rows
def create(self, data: dict, actor=None) -> T: def create(self, data: dict, actor=None) -> T:

View file

@ -35,7 +35,12 @@ def render_field(field, value):
def render_table(objects): def render_table(objects):
env = get_env() env = get_env()
template = get_crudkit_template(env, 'table.html') template = get_crudkit_template(env, 'table.html')
return template.render(objects=objects) if not objects:
return template.render(fields=[], rows=[])
proj = getattr(objects[0], "__crudkit_projection__", None)
rows = [obj.as_dict(proj) for obj in objects]
fields = list(rows[0].keys())
return template.render(fields=fields, rows=rows)
def render_form(model_cls, values, session=None): def render_form(model_cls, values, session=None):
env = get_env() env = get_env()

View file

@ -1,10 +1,10 @@
<table> <table>
{% if objects %} {% if rows %}
<tr> <tr>
{% for field in objects[0].__table__.columns %}<th>{{ field.name }}</th>{% endfor %} {% for field in fields if field != "id" %}<th>{{ field }}</th>{% endfor %}
</tr> </tr>
{% for obj in objects %} {% for row in rows %}
<tr>{% for field in obj.__table__.columns %}<td>{{ obj[field.name] }}</td>{% endfor %}</tr> <tr>{% for _, cell in row.items() if _ != "id" %}<td>{{ cell }}</td>{% endfor %}</tr>
{% endfor %} {% endfor %}
{% else %} {% else %}
<tr><th>No data.</th></tr> <tr><th>No data.</th></tr>