Skip to main content

stapel-geo

CI coverage pypi downloads python license llms.txt

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 facadenearby (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 Redis GEOSEARCH side-index backend ships for the hot set; Elasticsearch/Solr are named stubs.
  • Geocoder proxy — forward / structured / reverse geocoding behind a provider merge-registry (photon self-hosted default, nominatim keyless dev/fallback, google/yandex key-gated stubs), throttled, cached (30-day TTL) and spend-ledgered per call.
  • comm surfacegeo.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 with make contract).
  • Error reference: English · Русский.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stapel_geo-0.3.5.tar.gz (64.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stapel_geo-0.3.5-py3-none-any.whl (68.7 kB view details)

Uploaded Python 3

File details

Details for the file stapel_geo-0.3.5.tar.gz.

File metadata

  • Download URL: stapel_geo-0.3.5.tar.gz
  • Upload date:
  • Size: 64.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for stapel_geo-0.3.5.tar.gz
Algorithm Hash digest
SHA256 63808720d752d6d676004e00e0dc3d0da3edc01f58fc2bad22e977db75880e22
MD5 9855160ef3dfb5cdfc1c70d19747dbf3
BLAKE2b-256 047458b07b560117542092c6c2bc2e0fe7cc3ebe434e6796feb21b5b67290b7b

See more details on using hashes here.

Provenance

The following attestation bundles were made for stapel_geo-0.3.5.tar.gz:

Publisher: publish.yml on usestapel/stapel-geo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file stapel_geo-0.3.5-py3-none-any.whl.

File metadata

  • Download URL: stapel_geo-0.3.5-py3-none-any.whl
  • Upload date:
  • Size: 68.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for stapel_geo-0.3.5-py3-none-any.whl
Algorithm Hash digest
SHA256 8ee569d959a0db5a5ba6d83ea52ad12c17d75426d74f1d08789550619170bbfa
MD5 c55c508b90b4115f7d38e5dd0a2aa150
BLAKE2b-256 5702a19e3ed3c768fee2ee1cf443a0de659cad0ec047b877b70e91ee5c3d9f74

See more details on using hashes here.

Provenance

The following attestation bundles were made for stapel_geo-0.3.5-py3-none-any.whl:

Publisher: publish.yml on usestapel/stapel-geo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.4.1

2 files

0.4.0

2 files

0.3.6

2 files

This release

0.3.5 This release

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page