Geohash proximity search and geocoding for the Stapel framework — no GDAL, no PostGIS
Project description
stapel-geo
Geohash proximity search and geocoding for the Stapel framework — composable Django apps that deploy as a monolith or as microservices without changing module code. No GDAL, no PostGIS, no spatial database.
- Location tree — hierarchical reference places (
django-treenode): flat lat/lon points with an auto-encoded, indexed geohash and a stable cross-service UUID. No polygons. - Proximity search facade —
nearby(top-K) /radius(membership) /bbox(viewport, antimeridian-aware) behind one swappable backend key. The default runs on your primary database via geohash prefix expansion (correct across the equator, the antimeridian and the poles, ranked by exact haversine); a RedisGEOSEARCHside-index backend ships for the hot set; Elasticsearch/Solr are named stubs. - Geocoder proxy — forward / structured / reverse geocoding behind a
provider merge-registry (
photonself-hosted default,nominatimkeyless dev/fallback,google/yandexkey-gated stubs), throttled, cached (30-day TTL) and spend-ledgered per call. - comm surface —
geo.nearby/geo.radius/geo.bbox/geo.geohash_encode/geo.resolve: consumers (listings, calendar) query geo by name, never importing it.
Install
pip install stapel-geo # default backend needs nothing extra
pip install "stapel-geo[redis]" # + the Redis search backend
INSTALLED_APPS = [
# ...
"stapel_geo",
]
# urls.py — the canonical versioned surface /geo/api/v1/...
path("geo/", include("stapel_geo.urls"))
# ... or mount only the geocoder proxy:
path("geo/api/v1/geocoding/", include("stapel_geo.geocoding.urls"))
Plain manage.py migrate — any Django database backend works.
HTTP surface (/geo/api/v1/)
| Route | What |
|---|---|
locations/ |
List roots / search by name (?search=) |
locations/{id-or-uuid}/ |
Location detail (lat/lon/geohash, tree parent) |
locations/countries/ |
Root level of the tree |
locations/by-parent/{id}/ |
Children of a node |
locations/nearby-by-coords/?lat=&lon= |
Top-K nearest (exact distance_km) |
locations/nearby-by-geohash/?geohash= |
Same, geohash input |
locations/validate-uuid/{uuid}/ |
Cross-service reference check |
geocoding/search?q= |
Forward geocoding (JWT + throttle) |
geocoding/structured?city=&street= |
Structured address search |
geocoding/reverse?lat=&lon= |
Reverse geocoding |
Settings (STAPEL_GEO)
| Key | Default | Meaning |
|---|---|---|
SEARCH_BACKEND |
…search.postgres.PostgresGeoSearchBackend |
Search engine behind nearby/radius/bbox (dotted path). |
REDIS_URL / REDIS_GEO_KEY |
redis://localhost:6379/0 / stapel:geo:locations |
Redis backend connection + side-index key. |
GEOHASH_PRECISION |
8 |
Stored geohash precision (1-12 chars). |
NEARBY_PRECISION |
6 |
Default precision for coordinate nearby search. |
NEARBY_LIMIT / NEARBY_MAX_LIMIT |
10 / 50 |
Default / max search results. |
GEOCODER |
"photon" |
Default geocoder name (registry key). |
GEOCODERS |
{} |
Extra providers, merged over the built-ins (None removes). |
PHOTON_URL / PHOTON_LANGUAGES |
http://localhost:2322 / [default,en,de,fr] |
Photon provider knobs. |
NOMINATIM_URL |
https://nominatim.openstreetmap.org |
Nominatim base (public: 1 rps, dev/fallback). |
GEOCODER_TIMEOUT |
10 |
Geocoder HTTP timeout (s). |
GEOCODER_THROTTLE |
30/min |
DRF scoped throttle rate for the proxy. |
GEOCODE_CACHE_POLICY |
…geocoding.cache.LedgerCachePolicy |
Cache seam (dotted path). |
GEOCODE_CACHE_TTL_DAYS |
30 |
Default cache TTL. |
comm Functions
from stapel_core.comm import call
call("geo.nearby", {"lat": 49.61, "lon": 6.13, "limit": 5})
call("geo.radius", {"lat": 49.61, "lon": 6.13, "radius_km": 25})
call("geo.bbox", {"min_lat": 49, "min_lon": 5, "max_lat": 50, "max_lon": 7})
call("geo.geohash_encode", {"lat": 49.61, "lon": 6.13}) # -> {"geohash": ...}
call("geo.resolve", {"uuid": "<location-uuid>"})
min_lon > max_lon in geo.bbox means the box crosses the antimeridian.
Swapping the search backend
STAPEL_GEO = {"SEARCH_BACKEND": "stapel_geo.search.redis.RedisGeoSearchBackend"}
The Redis backend is a side index: the primary DB stays the source of
truth; post_save/post_delete keep it in sync and
RedisGeoSearchBackend().rebuild() re-indexes from scratch. Implement
stapel_geo.search.base.GeoSearchBackend (three verbs) to bring your own
engine — see MODULE.md.
Docs
- MODULE.md — extension points (agent-facing map).
- CHANGELOG.md — including what 0.3.0 removed and why.
docs/{schema,flows,errors}.json— the committed contract triad (regenerate withmake contract).- Error reference: English · Русский.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stapel_geo-0.3.2.tar.gz.
File metadata
- Download URL: stapel_geo-0.3.2.tar.gz
- Upload date:
- Size: 58.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af24ac8873fd28cfa97b8e1d1f1cfc096ca60949d6ea47882f5a3727206cfeed
|
|
| MD5 |
5b389e5bdc5600a80fc13b8fe0766534
|
|
| BLAKE2b-256 |
28dc957b400704d9093ca34d6bed3461e46db7fc4fae145a53663bfc9bdef6f8
|
Provenance
The following attestation bundles were made for stapel_geo-0.3.2.tar.gz:
Publisher:
publish.yml on usestapel/stapel-geo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stapel_geo-0.3.2.tar.gz -
Subject digest:
af24ac8873fd28cfa97b8e1d1f1cfc096ca60949d6ea47882f5a3727206cfeed - Sigstore transparency entry: 2188099394
- Sigstore integration time:
-
Permalink:
usestapel/stapel-geo@9a31524d7f6391e28ed646f8aeac101727bcc845 -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/usestapel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9a31524d7f6391e28ed646f8aeac101727bcc845 -
Trigger Event:
push
-
Statement type:
File details
Details for the file stapel_geo-0.3.2-py3-none-any.whl.
File metadata
- Download URL: stapel_geo-0.3.2-py3-none-any.whl
- Upload date:
- Size: 59.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12c79c0bd0383aaa461e845d4edb29688c6c53d5f4fbaf5c96fb7150413a7fcd
|
|
| MD5 |
f11879e557cef735a8090c0b70f286b6
|
|
| BLAKE2b-256 |
1d83a6b436340d2076c30a77b1377e9c8b4b73361a2b653934c403499a0358a2
|
Provenance
The following attestation bundles were made for stapel_geo-0.3.2-py3-none-any.whl:
Publisher:
publish.yml on usestapel/stapel-geo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stapel_geo-0.3.2-py3-none-any.whl -
Subject digest:
12c79c0bd0383aaa461e845d4edb29688c6c53d5f4fbaf5c96fb7150413a7fcd - Sigstore transparency entry: 2188099428
- Sigstore integration time:
-
Permalink:
usestapel/stapel-geo@9a31524d7f6391e28ed646f8aeac101727bcc845 -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/usestapel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9a31524d7f6391e28ed646f8aeac101727bcc845 -
Trigger Event:
push
-
Statement type: