feat(api): serve similar schools on the detail endpoint
Rides in the existing payload rather than a new endpoint: the page already makes one server fetch for its data, and /school/[slug] regenerates weekly, so the per-request cost is paid once per school per week. Wrapped so a failure in selection never 500s a page that is otherwise complete — the posture get_supplementary_data already takes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b571d9c549
commit
52b00ac752
2 files changed
+74
No files matched your search
@@ -41,6 +41,7 @@ from .data_loader import get_data_info as get_db_info
|
||||
from . import flags
|
||||
from .places import build_place_index, build_place_registry, places_for_urn
|
||||
from .schemas import METRIC_DEFINITIONS, PHASE_GROUPS, RANKING_COLUMNS, SCHOOL_COLUMNS
|
||||
from .similar_schools import select_similar
|
||||
from .utils import clean_for_json, convert_to_native
|
||||
|
||||
# Values to exclude from filter dropdowns (empty strings, non-applicable labels)
|
||||
@@ -265,6 +266,28 @@ def _places_payload(urn: int) -> list[dict]:
|
||||
return payload
|
||||
|
||||
|
||||
def _similar_schools_payload(urn: int, phase: str | None) -> list[dict]:
|
||||
"""Nearby schools this page may offer as alternatives.
|
||||
|
||||
Wrapped: a failure in selection must never 500 a page that is otherwise
|
||||
complete, which is the posture get_supplementary_data already takes. The
|
||||
section simply does not render.
|
||||
"""
|
||||
try:
|
||||
phase_text = (phase or "").lower()
|
||||
# All-through schools render with the primary template, which is what
|
||||
# decides the metric, so they are not secondary here.
|
||||
is_secondary = phase_text != "all-through" and "secondary" in phase_text
|
||||
return select_similar(load_latest_school_data(), int(urn), is_secondary)
|
||||
except Exception:
|
||||
import logging
|
||||
|
||||
logging.getLogger(__name__).exception(
|
||||
"Similar schools selection failed for urn=%s", urn
|
||||
)
|
||||
return []
|
||||
|
||||
|
||||
def _place_sitemap_rows(kinds: tuple[str, ...], registry=None) -> list[str]:
|
||||
"""A <url> per place, plus a phase variant wherever that phase clears the
|
||||
threshold on its own.
|
||||
@@ -975,6 +998,11 @@ async def get_school_details(request: Request, urn: int):
|
||||
# and authority both fall below the publish threshold has nowhere to
|
||||
# point, and the page renders without the module.
|
||||
"places": _places_payload(urn),
|
||||
# Nearby schools of the same phase and a comparable intake. Always
|
||||
# present on a build with this code; the frontend treats absent and
|
||||
# empty identically, which is what lets the two images deploy
|
||||
# independently.
|
||||
"similar_schools": _similar_schools_payload(urn, latest.get("phase")),
|
||||
"yearly_data": clean_for_json(school_data),
|
||||
# Supplementary data (null if not yet populated by Kestra)
|
||||
"ofsted": supplementary.get("ofsted"),
|
||||
|
||||
Reference in new issue
Block a user