Nomos Zonage -- Dentist Geographic Zoning¶
The nomos_zonage app manages French geographic zoning data for dentist accessibility (Carto Sante program). It maps communes to service-level categories indicating how well-served an area is for dental care.
Architecture¶
- Source data: Excel files from official Carto Sante distributions
- Import: Management commands load postal mappings and zoning data
- Access: Django admin only (no custom views)
Models¶
| Model | Description |
|---|---|
PostalCodeMapping |
INSEE code <-> postal code correspondence (unique together) |
CommuneZonage |
Commune zoning level on a 5-point scale |
ZonageImportLog |
Tracks import operations with status and statistics |
Zoning Categories¶
| Level | Key | Description |
|---|---|---|
| 1 | tres_sous_dotee |
Very underserved |
| 2 | sous_dotee |
Underserved |
| 3 | intermediaire |
Intermediate |
| 4 | bien_dotee |
Well-served |
| 5 | sur_dotee |
Over-served |
Constants defined in apps/nomos_zonage/constants.py with CSS classes for badge display.
Management Commands¶
| Command | Description |
|---|---|
postal_mapping_import |
Import postal code <-> INSEE mappings |
zonage_import |
Import zoning data from Excel |
zonage_link_orgs |
Link organizations to their zoning level |
Operations -- Full Import Procedure¶
Overview¶
The pipeline has 3 steps that must run in order:
- postal_mapping_import -- loads the postal code ↔ INSEE commune code lookup table
- zonage_import -- loads commune zoning levels from the Carto Santé Excel export
- zonage_link_orgs -- resolves each organization's postal code → INSEE code → zonage and writes it to the org record
Source files¶
| File | Source | Default location | Format |
|---|---|---|---|
laposte_hexasmal.csv |
data.gouv.fr (La Poste) | data/reference/laposte_hexasmal.csv (bundled in repo) |
CSV |
export_zoning.xlsx |
Carto Santé (ARS) | No default -- must be provided via --source-file |
Excel, sheet "Data", headers on row 4 |
Step-by-step¶
1. Upload the zoning file to the server¶
Copy the Carto Santé Excel export to a location accessible by the container:
2. Open a shell in the web container¶
All commands below are run inside this shell.
3. Import postal code mappings (if needed)¶
This table is rarely updated. Only re-run if La Poste has published a new version or the table is empty.
# Preview
python manage.py postal_mapping_import --dry-run
# Import (uses bundled CSV at data/reference/laposte_hexasmal.csv)
python manage.py postal_mapping_import
4. Import zoning data¶
# Preview
python manage.py zonage_import --source-file /tmp/cartosante/export_zoning.xlsx --dry-run
# Import (--truncate replaces all existing data)
python manage.py zonage_import --source-file /tmp/cartosante/export_zoning.xlsx --truncate
5. Link organizations to zoning levels¶
# Preview resolution stats
python manage.py zonage_link_orgs --dry-run
# Apply (--force overwrites existing zonage values)
python manage.py zonage_link_orgs --force
Resolution strategy (zonage_link_orgs)¶
The command resolves an organization's zonage in this order:
- Direct INSEE -- use the org's existing
address_insee_codeif it matches a known zonage - Single postal match -- if the postal code maps to exactly one commune, use it
- City name match -- if multiple communes share a postal code, match on normalized city name
- CEDEX fallback -- if the postal code is not in the mapping (common for CEDEX codes), derive the department from the first 2 digits, strip "CEDEX" from the city name, and match against all communes in that department
Unresolved organizations are logged in the output stats.
Checking results¶
- Admin: browse
PostalCodeMapping,CommuneZonage, andZonageImportLogin Django admin - Frontend: /annuaire/zonage/ shows organizations with their zoning levels
- Import logs track status, record counts, duration, and errors for each run