diff --git a/database_api/model_taskitem.py b/database_api/model_taskitem.py
index 8e7318ef..28ac5e4a 100644
--- a/database_api/model_taskitem.py
+++ b/database_api/model_taskitem.py
@@ -4,6 +4,7 @@
from database_api.planexe_db_singleton import db
from sqlalchemy_utils import UUIDType
from sqlalchemy import JSON
+from sqlalchemy.orm import column_property
class TaskState(enum.Enum):
pending = 1
@@ -70,6 +71,11 @@ class TaskItem(db.Model):
# Artifact schema/version marker (legacy snapshots are NULL/1, split-storage snapshots are 2+).
run_artifact_layout_version = db.Column(db.Integer, nullable=True, default=None)
+ # Lightweight admin/UI helpers; avoids loading large payload columns just to render links.
+ has_generated_report_html = column_property(generated_report_html.isnot(None))
+ has_run_zip_snapshot = column_property(run_zip_snapshot.isnot(None))
+ has_run_track_activity_jsonl = column_property(run_track_activity_jsonl.isnot(None))
+
def __repr__(self):
return f"{self.id}: {self.timestamp_created}, {self.state}, {self.prompt!r}, parameters: {self.parameters!r}"
diff --git a/frontend_multi_user/src/planexe_modelviews.py b/frontend_multi_user/src/planexe_modelviews.py
index 5989cf8b..e28b41e8 100644
--- a/frontend_multi_user/src/planexe_modelviews.py
+++ b/frontend_multi_user/src/planexe_modelviews.py
@@ -13,6 +13,7 @@
from markupsafe import Markup
from flask import url_for, abort, redirect, Response
from flask_login import current_user
+from sqlalchemy.orm import defer
class AdminOnlyModelView(ModelView):
"""Restrict admin views to authenticated admin users only."""
@@ -135,23 +136,30 @@ class TaskItemView(AdminOnlyModelView):
'prompt': lambda v, c, m, p: m.prompt[:100] + '...' if m.prompt and len(m.prompt) > 100 else m.prompt,
'view_plan': lambda v, c, m, p: Markup(
f'View'
- ) if m.generated_report_html else '—',
+ ) if m.has_generated_report_html else '—',
'generated_report_html': lambda v, c, m, p: Markup(
- f'Download ({len(m.generated_report_html.encode("utf-8")) / 1024:.1f} KB)'
- ) if m.generated_report_html else '—',
+ f'Download'
+ ) if m.has_generated_report_html else '—',
'run_zip_snapshot': lambda v, c, m, p: Markup(
- f'Download ({len(m.run_zip_snapshot) / 1024:.1f} KB)'
- ) if m.run_zip_snapshot else '—',
+ f'Download'
+ ) if m.has_run_zip_snapshot else '—',
'run_activity_overview_json': lambda v, c, m, p: (
json.dumps(m.run_activity_overview_json, ensure_ascii=False)[:120] + '...'
if m.run_activity_overview_json and len(json.dumps(m.run_activity_overview_json, ensure_ascii=False)) > 120
else (json.dumps(m.run_activity_overview_json, ensure_ascii=False) if m.run_activity_overview_json else '—')
),
'run_track_activity': lambda v, c, m, p: Markup(
- f'Download ({((m.run_track_activity_bytes if m.run_track_activity_bytes is not None else len(m.run_track_activity_jsonl.encode("utf-8"))) / 1024):.1f} KB)'
- ) if m.run_track_activity_jsonl else '—',
+ f'Download'
+ ) if m.has_run_track_activity_jsonl else '—',
}
+ def get_query(self):
+ return super().get_query().options(
+ defer(self.model.generated_report_html),
+ defer(self.model.run_zip_snapshot),
+ defer(self.model.run_track_activity_jsonl),
+ )
+
class NonceItemView(AdminOnlyModelView):
"""Custom ModelView for NonceItem"""
def __init__(self, model, *args, **kwargs):