diff --git a/crudkit/dsl.py b/crudkit/dsl.py index a9ee931..5a4e5b8 100644 --- a/crudkit/dsl.py +++ b/crudkit/dsl.py @@ -108,6 +108,11 @@ def build_query(Model, spec: QuerySpec, eager_policy=None): col = getattr(Model, key[1:] if desc_ else key) stmt = stmt.order_by(desc(col) if desc_ else asc(col)) + if not spec.order_by and spec.page and spec.per_page: + pk_cols = inspect(Model).primary_key + if pk_cols: + stmt = stmt.order_by(*(asc(c) for c in pk_cols)) + # eager loading if eager_policy: opts = eager_policy(Model, spec.expand) diff --git a/crudkit/html/templates/crudkit/form.html b/crudkit/html/templates/crudkit/form.html index 5f3bfb3..761658a 100644 --- a/crudkit/html/templates/crudkit/form.html +++ b/crudkit/html/templates/crudkit/form.html @@ -1,3 +1,3 @@ -{% import "_macros.html" as ui %} +{% import "crudkit/_macros.html" as ui %} {% set action = url_for('frags.save', model=model) %} {{ ui.form(schema, action, method="POST", obj_id=obj.id if obj else None, hx=true) }} \ No newline at end of file diff --git a/crudkit/html/templates/crudkit/lis.html b/crudkit/html/templates/crudkit/lis.html index e9b1813..3ce62e7 100644 --- a/crudkit/html/templates/crudkit/lis.html +++ b/crudkit/html/templates/crudkit/lis.html @@ -1,2 +1,2 @@ -{% import "_macros.html" as ui %} +{% import "crudkit/_macros.html" as ui %} {{ ui.lis(items, label_path=label_path, sublabel_path=sublabel_path, getp=getp) }} diff --git a/crudkit/html/templates/crudkit/options.html b/crudkit/html/templates/crudkit/options.html index 34d6a2b..0f66d2d 100644 --- a/crudkit/html/templates/crudkit/options.html +++ b/crudkit/html/templates/crudkit/options.html @@ -1,3 +1,3 @@ {# Renders only rows #} -{% import "_macros.html" as ui %} +{% import "crudkit/_macros.html" as ui %} {{ ui.options(items, value_attr=value_attr, label_path=label_path, getp=getp) }} diff --git a/crudkit/html/templates/crudkit/row.html b/crudkit/html/templates/crudkit/row.html index a3ac629..719c0ba 100644 --- a/crudkit/html/templates/crudkit/row.html +++ b/crudkit/html/templates/crudkit/row.html @@ -1,2 +1,2 @@ -{% import "_macros.html" as ui %} +{% import "crudkit/_macros.html" as ui %} {{ ui.rows([obj], fields, getp=getp) }} \ No newline at end of file diff --git a/crudkit/html/templates/crudkit/rows.html b/crudkit/html/templates/crudkit/rows.html index 7fafa3a..1c740f1 100644 --- a/crudkit/html/templates/crudkit/rows.html +++ b/crudkit/html/templates/crudkit/rows.html @@ -1,3 +1,3 @@ -{% import "_macros.html" as ui %} +{% import "crudkit/_macros.html" as ui %} {{ ui.rows(items, fields, getp=getp) }} {{ ui.pager(model, page, pages, per_page, sort, filters) }} diff --git a/crudkit/html/ui_fragments.py b/crudkit/html/ui_fragments.py index 525c6e5..03182a7 100644 --- a/crudkit/html/ui_fragments.py +++ b/crudkit/html/ui_fragments.py @@ -20,7 +20,7 @@ def make_fragments_blueprint(db_session_factory, registry: Dict[str, Any], *, na GET //frag/rows -> ... + pager markup if wanted GET //frag/form ->
...
(auto-generated) """ - bp = Blueprint(name, __name__, template_folder="templates/crudkit") + bp = Blueprint(name, __name__, template_folder="templates") def session(): return scoped_session(db_session_factory)() def _parse_filters(args): @@ -74,7 +74,7 @@ def make_fragments_blueprint(db_session_factory, registry: Dict[str, Any], *, na s = session(); svc = CrudService(s, default_eager_policy) items, _ = svc.list(Model, spec) - return render_template("options.html", items=items, value_attr=value_attr, label_path=label_path, getp=_getp) + return render_template("crudkit/options.html", items=items, value_attr=value_attr, label_path=label_path, getp=_getp) @bp.get("//frag/lis") def lis(model): @@ -91,7 +91,7 @@ def make_fragments_blueprint(db_session_factory, registry: Dict[str, Any], *, na s = session(); svc = CrudService(s, default_eager_policy) rows, total = svc.list(Model, spec) pages = (ceil(total / per_page) if page and per_page else 1) - return render_template("lis.html", items=rows, label_path=label_path, sublabel_path=sublabel_path, page=page or 1, per_page=per_page or 1, total=total, model=model, sort=sort, filters=filters, getp=_getp) + return render_template("crudkit/lis.html", items=rows, label_path=label_path, sublabel_path=sublabel_path, page=page or 1, per_page=per_page or 1, total=total, model=model, sort=sort, filters=filters, getp=_getp) @bp.get("//frag/rows") def rows(model): @@ -108,7 +108,7 @@ def make_fragments_blueprint(db_session_factory, registry: Dict[str, Any], *, na s = session(); svc = CrudService(s, default_eager_policy) rows, total = svc.list(Model, spec) pages = max(1, ceil(total / per_page)) - return render_template("rows.html", items=rows, fields=fields, page=page, pages=pages, per_page=per_page, total=total, model=model, sort=sort, filters=filters, getp=_getp) + return render_template("crudkit/rows.html", items=rows, fields=fields, page=page, pages=pages, per_page=per_page, total=total, model=model, sort=sort, filters=filters, getp=_getp) @bp.get("//frag/form") def form(model): @@ -123,7 +123,7 @@ def make_fragments_blueprint(db_session_factory, registry: Dict[str, Any], *, na schema = build_form_schema(Model, s, obj=obj, include=include) hx = request.args.get("hx", type=int) == 1 - return render_template("form.html", model=model, obj=obj, schema=schema, hx=hx) + return render_template("crudkit/form.html", model=model, obj=obj, schema=schema, hx=hx) def coerce_form_types(Model, data: dict) -> dict: """Turn HTML string inputs into the Python types your columns expect."""