2026-08-21 18:11:56 +01:00
|
|
|
"""Curated London localities, defined by the postcode districts they cover.
|
|
|
|
|
|
|
|
|
|
The GIAS `town` field puts 1,819 London schools under the single value
|
|
|
|
|
"London", so it cannot answer "schools in Battersea" — a query that appears in
|
|
|
|
|
the Search Console baseline. No single field can: parliamentary constituency
|
|
|
|
|
gives Battersea but not Canary Wharf; postcodes.io's admin_ward gives Canary
|
|
|
|
|
Wharf but not Battersea; neither gives Clapham or Shoreditch, which are postal
|
|
|
|
|
and colloquial rather than administrative.
|
|
|
|
|
|
|
|
|
|
So this is curated. Where a locality ends is a judgement, not a fact, and a
|
|
|
|
|
reviewable file is the honest place for a judgement. No new ingestion is
|
|
|
|
|
needed — the corpus already carries postcodes.
|
|
|
|
|
|
|
|
|
|
This is the canonical copy. `pipeline/transform/seeds/locality_outcodes.csv`
|
|
|
|
|
mirrors it for anyone querying the warehouse directly; the backend image does
|
|
|
|
|
not contain `pipeline/`, which is why the module rather than the seed is
|
|
|
|
|
canonical. Same arrangement as `backend/gias_codes.py`.
|
|
|
|
|
|
|
|
|
|
A locality whose outcodes hold fewer than MIN_SCHOOLS schools is not
|
|
|
|
|
published, so a typo produces no page rather than an empty one. Places that
|
|
|
|
|
fail that check are logged at startup, because a locality you meant to publish
|
|
|
|
|
quietly not appearing is the failure worth hearing about.
|
2026-08-21 19:06:55 +01:00
|
|
|
|
|
|
|
|
Two rules for anything added here.
|
|
|
|
|
|
|
|
|
|
**Sub-borough districts only.** A London borough is a local authority and
|
|
|
|
|
already has a page at /schools/authority/[la] covering all of its schools; a
|
|
|
|
|
locality defined by two or three outcodes would be a partial, near-duplicate
|
|
|
|
|
subset of it. Hackney, Islington, Greenwich and Ealing were all in the first
|
|
|
|
|
draft for that reason and have been removed.
|
|
|
|
|
|
|
|
|
|
**The slug must not match a GIAS town.** "Richmond" did — GIAS has a Richmond
|
|
|
|
|
in North Yorkshire with 37 schools — so the London one could never publish.
|
|
|
|
|
The registry skips any locality that collides and logs it.
|
2026-08-21 18:11:56 +01:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# slug -> (display name, outcodes)
|
|
|
|
|
LOCALITY_OUTCODES: dict[str, tuple[str, tuple[str, ...]]] = {
|
|
|
|
|
"battersea": ("Battersea", ("SW11",)),
|
|
|
|
|
"canary-wharf": ("Canary Wharf", ("E14",)),
|
|
|
|
|
"clapham": ("Clapham", ("SW4",)),
|
|
|
|
|
"shoreditch": ("Shoreditch", ("EC2A", "E1")),
|
|
|
|
|
"peckham": ("Peckham", ("SE15",)),
|
|
|
|
|
"brixton": ("Brixton", ("SW2", "SW9")),
|
|
|
|
|
"camden-town": ("Camden Town", ("NW1",)),
|
|
|
|
|
"wimbledon": ("Wimbledon", ("SW19",)),
|
|
|
|
|
"putney": ("Putney", ("SW15",)),
|
|
|
|
|
"fulham": ("Fulham", ("SW6",)),
|
|
|
|
|
"chiswick": ("Chiswick", ("W4",)),
|
|
|
|
|
"stratford": ("Stratford", ("E15",)),
|
|
|
|
|
"walthamstow": ("Walthamstow", ("E17",)),
|
|
|
|
|
"tooting": ("Tooting", ("SW17",)),
|
|
|
|
|
"dulwich": ("Dulwich", ("SE21", "SE22")),
|
|
|
|
|
}
|