updates for secondary schools
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 46s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m15s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
All checks were successful
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 46s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m15s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
This commit is contained in:
@@ -218,6 +218,9 @@ async def get_schools(
|
||||
radius: float = Query(5.0, ge=0.1, le=50, description="Search radius in miles"),
|
||||
page: int = Query(1, ge=1, le=1000, description="Page number"),
|
||||
page_size: int = Query(None, ge=1, le=100, description="Results per page"),
|
||||
gender: Optional[str] = Query(None, description="Filter by gender (Mixed/Boys/Girls)", max_length=50),
|
||||
admissions_policy: Optional[str] = Query(None, description="Filter by admissions policy", max_length=100),
|
||||
has_sixth_form: Optional[str] = Query(None, description="Filter by sixth form presence: yes/no", max_length=3),
|
||||
):
|
||||
"""
|
||||
Get list of schools with pagination.
|
||||
@@ -253,6 +256,13 @@ async def get_schools(
|
||||
prev_rwm = df_prev[["urn", "rwm_expected_pct"]].rename(
|
||||
columns={"rwm_expected_pct": "prev_rwm_expected_pct"}
|
||||
)
|
||||
if "attainment_8_score" in df_prev.columns:
|
||||
prev_rwm = prev_rwm.merge(
|
||||
df_prev[["urn", "attainment_8_score"]].rename(
|
||||
columns={"attainment_8_score": "prev_attainment_8_score"}
|
||||
),
|
||||
on="urn", how="outer"
|
||||
)
|
||||
df_latest = df_latest.merge(prev_rwm, on="urn", how="left")
|
||||
|
||||
# Phase filter
|
||||
@@ -270,6 +280,16 @@ async def get_schools(
|
||||
schools_df_phase_mask = df_latest["phase"].str.lower().str.contains(phase_substr, na=False)
|
||||
df_latest = df_latest[schools_df_phase_mask]
|
||||
|
||||
# Secondary-specific filters (after phase filter)
|
||||
if gender:
|
||||
df_latest = df_latest[df_latest["gender"].str.lower() == gender.lower()]
|
||||
if admissions_policy:
|
||||
df_latest = df_latest[df_latest["admissions_policy"].str.lower() == admissions_policy.lower()]
|
||||
if has_sixth_form == "yes":
|
||||
df_latest = df_latest[df_latest["age_range"].str.contains("18", na=False)]
|
||||
elif has_sixth_form == "no":
|
||||
df_latest = df_latest[~df_latest["age_range"].str.contains("18", na=False)]
|
||||
|
||||
# Include key result metrics for display on cards
|
||||
location_cols = ["latitude", "longitude"]
|
||||
result_cols = [
|
||||
@@ -278,6 +298,7 @@ async def get_schools(
|
||||
"rwm_expected_pct",
|
||||
"rwm_high_pct",
|
||||
"prev_rwm_expected_pct",
|
||||
"prev_attainment_8_score",
|
||||
"reading_expected_pct",
|
||||
"writing_expected_pct",
|
||||
"maths_expected_pct",
|
||||
@@ -510,14 +531,33 @@ async def get_filter_options(request: Request):
|
||||
# Phases: return values from data, ordered sensibly
|
||||
phases = sorted(df["phase"].dropna().unique().tolist()) if "phase" in df.columns else []
|
||||
|
||||
secondary_df = df[df["attainment_8_score"].notna()] if "attainment_8_score" in df.columns else df.iloc[0:0]
|
||||
genders = sorted(secondary_df["gender"].dropna().unique().tolist()) if "gender" in secondary_df.columns else []
|
||||
admissions_policies = sorted(secondary_df["admissions_policy"].dropna().unique().tolist()) if "admissions_policy" in secondary_df.columns else []
|
||||
|
||||
return {
|
||||
"local_authorities": sorted(df["local_authority"].dropna().unique().tolist()),
|
||||
"school_types": sorted(df["school_type"].dropna().unique().tolist()),
|
||||
"years": sorted(df["year"].dropna().unique().tolist()),
|
||||
"phases": phases,
|
||||
"genders": genders,
|
||||
"admissions_policies": admissions_policies,
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/la-averages")
|
||||
@limiter.limit(f"{settings.rate_limit_per_minute}/minute")
|
||||
async def get_la_averages(request: Request):
|
||||
"""Get per-LA average Attainment 8 score for secondary schools in the latest year."""
|
||||
df = load_school_data()
|
||||
if df.empty:
|
||||
return {"year": 0, "secondary": {"attainment_8_by_la": {}}}
|
||||
latest_year = int(df["year"].max())
|
||||
sec_df = df[(df["year"] == latest_year) & df["attainment_8_score"].notna()]
|
||||
la_avg = sec_df.groupby("local_authority")["attainment_8_score"].mean().round(1).to_dict()
|
||||
return {"year": latest_year, "secondary": {"attainment_8_by_la": la_avg}}
|
||||
|
||||
|
||||
@app.get("/api/national-averages")
|
||||
@limiter.limit(f"{settings.rate_limit_per_minute}/minute")
|
||||
async def get_national_averages(request: Request):
|
||||
|
||||
Reference in New Issue
Block a user