Skip to main content

django-hostmap

Host-based URL routing and host-aware reversing for Django, with zero call-site changes.

django-hostmap routes requests to different URLconfs by host (subdomain or full domain) and makes URL reversing host-aware without changing a single call site: the stock reverse(), reverse_lazy() and {% url %} keep working everywhere, including inside third-party apps. Links within the current host stay path-relative, exactly as Django produces them; links to views on another host come back as absolute URLs. Configuration is one declarative host map in settings plus one middleware.

It is the ecosystem's replacement for django-hosts, whose parallel reverse API forces invasive changes across templates and Python code and cannot fix third-party apps that call django.urls.reverse().

Installation

pip install django-hostmap
INSTALLED_APPS = [
    # ...
    "hostmap",
]

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "hostmap.middleware.HostmapMiddleware",  # before CommonMiddleware
    "django.middleware.common.CommonMiddleware",
    # ...
]

ROOT_URLCONF remains required (Django needs it at startup) and should point at the default entry's URLconf (hostmap.W003 warns on mismatch).

The host map

HOSTMAP = {
    "www": {"subdomain": "www", "urlconf": "config.urls.www"},
    "api": {"subdomain": "api", "urlconf": "config.urls.api"},
    "apex": {"host": "example.com", "redirect_to": "www"},
}
HOSTMAP_PARENT_DOMAIN = "example.com"
HOSTMAP_DEFAULT = "www"

With www active:

Call Returns
reverse("blog:index") /blog/ (byte-identical to stock Django)
reverse("api:user-detail", args=[7]) https://api.example.com/users/7/
{% url "api:user-detail" 7 %} the absolute URL, no template changes

Same-host links stay relative; cross-host links come back absolute. Nothing at the call site changes.

Settings

Setting Default Description
HOSTMAP {} The host map. Empty map disables all behaviour
HOSTMAP_PARENT_DOMAIN "" Domain joined to subdomain entries
HOSTMAP_DEFAULT "" Entry for unmatched hosts and out-of-request reversing
HOSTMAP_PATCH_REVERSE True Make stock reverse() / {% url %} host-aware
HOSTMAP_SCHEME "https" Scheme for cross-host absolute URLs
HOSTMAP_PORT "" Port appended to all generated hosts
HOSTMAP_UNMATCHED "default" "default" routes unmatched hosts to the default entry; "reject" returns 404
HOSTMAP_REDIRECT_PERMANENT True redirect_to entries use 301, else 302
HOSTMAP_ALLOW_UNTESTED_DJANGO False Explicit opt-out that downgrades the untested-Django reverse-patch refusal from hostmap.E009 to hostmap.W005

Explicit API

For code that needs an absolute URL regardless of the active host (emails, Celery tasks, API payloads, webhooks):

from hostmap.urls import reverse, build_absolute_uri, use_host

build_absolute_uri("api:user-detail", args=[7])          # always absolute
with use_host("api"):
    reverse("user-detail", args=[7])                     # api active

with use_host(host="acme.example.com"):                  # a wildcard host
    reverse("dashboard")

Development story

Modern browsers resolve *.localhost to loopback (RFC 6761), so the whole map works locally with no /etc/hosts edits:

HOSTMAP_PARENT_DOMAIN = "localhost"
HOSTMAP_SCHEME = "http"
HOSTMAP_PORT = "8000"
ALLOWED_HOSTS = [".localhost"]

Behind a proxy

Host routing is only as good as the Host header that reaches Django. Behind a reverse proxy, either the proxy passes Host through unchanged or the deployment sets USE_X_FORWARDED_HOST = True with the proxy sending X-Forwarded-Host. Misrouted hosts behind nginx are otherwise the first support issue.

Escape hatch

HOSTMAP_PATCH_REVERSE = False degrades cleanly to routing-only: the stock reverse() is left untouched (cross-host links regress to paths), routing keeps working, and the explicit API still works. Set it if a Django upgrade lands before a compatible django-hostmap release; the startup self-test and hostmap.E009/hostmap.W004 catch a Django upgrade running ahead of the package's tested ceiling before anything breaks. With the patch active (the default), an unverified Django version is hostmap.E009, an Error that fails startup, since the patch hooks a private resolver seam that has not been verified there; with the patch off, the same condition is only hostmap.W004, a Warning, since routing-only operation never touches that seam.

Diagnostics

manage.py hostmap    # print the resolved map for the current settings

Licence

MIT. See LICENSE.

Metadata

Release files for django-hostmap 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-hostmap 1.1.1
File Size Uploaded Provenance Actions
django_hostmap-1.1.1.tar.gz 33.9 kB With provenance Details for django_hostmap-1.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for django-hostmap 1.1.1
File Interpreter ABI Platform Actions
django_hostmap-1.1.1-py3-none-any.whl Python 3 none any Details for django_hostmap-1.1.1-py3-none-any.whl

Total release size: 60.4 kB

Release files / django_hostmap-1.1.1.tar.gz

Download URL django_hostmap-1.1.1.tar.gz
Size 33.9 kB
Tags Source
SHA-256 checksum
How to use checksums
8e014e0b4a3de9f39d64d21dac63e9a957de3d9fabe44cb465452d22a985a6f6
BLAKE2b-256 checksum
How to use checksums
0f0dac2fbafa874f53a2e27c079b926652f3e618102f9682f91320b5fe9f8f72
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release files / django_hostmap-1.1.1-py3-none-any.whl

Download URL django_hostmap-1.1.1-py3-none-any.whl
Size 26.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a7b163b8eab84fe911bad3ceee4a7f7af4777174040a6ee7d26b934aa1f6f7ff
BLAKE2b-256 checksum
How to use checksums
796450383331575a39a278c7956f71c36b7a0f876f9449abcba0fa3f36c3409b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Security for django-hostmap 1.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for django_hostmap-1.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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