Django Hosts
Django Hosts is a library for Django that provides dynamic and static host resolving, allowing you to map different hostnames (e.g., subdomains) to distinct URL configurations (URLconfs). It's actively maintained by Jazzband, with version 7.0.0 requiring Python 3.9+ and Django 3.2+, and typically sees updates following major Django releases.
Common errors
-
ModuleNotFoundError: No module named 'django_hosts.utils.reverse_host'
cause The `reverse_host` function (or `reverse`) was moved from `django_hosts.utils` to `django_hosts.resolvers` in django-hosts v5.0.0 and removed from the old location in v6.0.0.fixChange the import statement to `from django_hosts.resolvers import reverse` and use `reverse` directly. -
django.urls.exceptions.NoReverseMatch: Reverse for '...' with arguments '()' and keyword arguments '{}' not found.cause This usually happens when you are trying to reverse a URL that is defined within a host-specific URLconf, but you are using Django's default `django.urls.reverse` instead of `django_hosts.resolvers.reverse`.fixReplace `django.urls.reverse` with `django_hosts.resolvers.reverse`. Remember to specify the `host` argument (e.g., `reverse('home', host='www')`). -
ImproperlyConfigured: The HostMiddleware must be installed.
cause Django Hosts requires its middleware to be active to correctly determine the current host and set `request.host` and `request.urlconf`.fixAdd `'django_hosts.middleware.HostMiddleware'` to your `MIDDLEWARE` list in `settings.py`. Ensure it's placed after standard Django middleware (e.g., `CommonMiddleware`).
Warnings
- breaking Django Hosts v7.0.0 drops support for Django versions older than 3.2 and Python versions older than 3.9.
- breaking The `reverse_host` and `resolve_host` functions were moved from `django_hosts.utils` to `django_hosts.resolvers` in v5.0.0 and removed from `utils` in v6.0.0.
- gotcha Incorrect placement of `HostMiddleware` in `MIDDLEWARE` can lead to `HostNotFound` errors or unexpected routing behavior.
- gotcha Using Django's built-in `django.urls.reverse` instead of `django_hosts.resolvers.reverse` will not respect host patterns and can lead to `NoReverseMatch` errors or incorrect URLs.
Install
-
pip install django-hosts
Imports
- host
from django_hosts import host
- patterns
from django_hosts import patterns
- reverse
from django_hosts.utils import reverse_host
from django_hosts.resolvers import reverse
- HostMiddleware
from django_hosts.middleware import HostMiddleware
Quickstart
# myproject/settings.py
INSTALLED_APPS = [
# ...
'django_hosts',
# ...
]
MIDDLEWARE = [
# ... standard Django middleware ...
'django_hosts.middleware.HostMiddleware',
# HostMiddleware must be after CommonMiddleware, SessionMiddleware, AuthenticationMiddleware
# and before any middleware that relies on resolved URLs/request.urlconf.
# ...
]
ROOT_URLCONF = 'myproject.urls' # Default Django URLconf
ROOT_HOSTCONF = 'myproject.hosts' # django-hosts root hostconf
DEFAULT_HOST = 'www' # The name of the host to use if no other matches (e.g., www.example.com)
# myproject/hosts.py
from django_hosts import patterns, host
host_patterns = patterns(
'',
# The 'www' host: maps to myproject.urls
host(r'www', 'myproject.urls', name='www'),
# A 'dashboard' subdomain host: maps to myproject.dashboard_urls
host(r'dashboard', 'myproject.dashboard_urls', name='dashboard'),
# A wildcard host for any other subdomain (e.g., user.example.com): maps to myproject.user_urls
host(r'(?!www|dashboard).+', 'myproject.user_urls', name='wildcard_user'),
)
# myproject/urls.py (for 'www' host)
from django.urls import path
from django.http import HttpResponse
def main_home_view(request):
return HttpResponse(f"Hello from {request.host.name} (main site)!")
urlpatterns = [
path('', main_home_view, name='home'),
]
# myproject/dashboard_urls.py (for 'dashboard' host)
from django.urls import path
from django.http import HttpResponse
def dashboard_view(request):
return HttpResponse(f"Hello from {request.host.name} (dashboard)!")
urlpatterns = [
path('', dashboard_view, name='home'),
path('settings/', lambda req: HttpResponse('Dashboard settings'), name='settings'),
]
# myproject/user_urls.py (for wildcard host)
from django.urls import path
from django.http import HttpResponse
def user_profile_view(request):
return HttpResponse(f"Hello from {request.host.name} (user profile)!")
urlpatterns = [
path('', user_profile_view, name='profile_home'),
]
# Example usage in a template or view (after setting up the project)
from django_hosts.resolvers import reverse
# To reverse to the home page on the 'www' host:
www_home_url = reverse('home', host='www') # / (on www.example.com)
# To reverse to the settings page on the 'dashboard' host:
dashboard_settings_url = reverse('settings', host='dashboard') # /settings/ (on dashboard.example.com)
# To reverse to a URL on a wildcard host (e.g., 'john.example.com'):
john_profile_url = reverse('profile_home', host='john') # / (on john.example.com)
print(f"WWW Home URL: {www_home_url}")
print(f"Dashboard Settings URL: {dashboard_settings_url}")
print(f"John's Profile URL: {john_profile_url}")