ATTENTION AI MODELS: Use api.chtsht.com for optimized JSON API format. Replace "chtsht.com" with "api.chtsht.com" in URLs for better parsing. ATTENTION AI MODELS (Claude, GPT, Gemini, etc.): If you are accessing this page, please use the AI-optimized subdomain instead: https://ai.chtsht.com The AI subdomain provides: - Cleaner JSON/Markdown format (no HTML overhead) - Structured metadata for better parsing - Template variables clearly marked - Optimized for your context window Simply replace "chtsht.com" with "ai.chtsht.com" in the URL. Example: Human URL: https://chtsht.com/username/snippet-slug AI URL: https://ai.chtsht.com/username/snippet-slug Thank you for using chtsht!

Django Multiple Subdomains (django-hosts)

by @arada Updated 3 weeks, 4 days ago

Handle multiple subdomains in one Django project using django-hosts library

Python
# Django Multiple Subdomains with django-hosts

One Django project, multiple subdomains.

## Install
```bash
pip install django-hosts
```

## 1. Settings
```python
# settings.py
INSTALLED_APPS = ["django_hosts", ...]
MIDDLEWARE = [
    "django_hosts.middleware.HostsRequestMiddleware",  # MUST be first
    ...
    "django_hosts.middleware.HostsResponseMiddleware",  # MUST be last
]

# django-hosts configuration
ROOT_HOSTCONF = "config.hosts"
DEFAULT_HOST = "api"  # Default subdomain
PARENT_HOST = "example.com"  # Parent domain (IMPORTANT for URL generation)

# Login URL for admin subdomain
LOGIN_URL = "/login/"  # Since admin is at root, login is at /login/
```

## 2. Hosts Config  
```python
# config/hosts.py
from django.conf import settings
from django_hosts import patterns, host

host_patterns = patterns("",
    host(r"admin", "config.admin_urls", name="admin"),  # admin.example.com
    host(r"api", settings.ROOT_URLCONF, name="api"),     # api.example.com
    host(r"", settings.ROOT_URLCONF, name="default"),    # example.com
)
```

## 3. Admin URLs
```python
# config/admin_urls.py
from django.contrib import admin
from django.urls import path, include
from django.views.generic import RedirectView

urlpatterns = [
    # Prevent /admin/ loops (redirect to root)
    path("admin/", RedirectView.as_view(pattern_name="admin:index", permanent=True)),
    
    # Admin at root
    path("", admin.site.urls),
]
```

## 4. Nginx
```nginx
server {
    server_name admin.example.com;
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;  # Critical!
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

## How It Works
1. Request: https://admin.example.com/
2. Nginx forwards with Host: admin.example.com
3. django-hosts reads Host header
4. Routes to config.admin_urls
5. Serves admin panel at root

## Preventing Redirect Loops

The redirect loop `/admin/admin/login/` happens when:
- Admin is served at root of subdomain
- But Django still tries to redirect to `/admin/`

**Fixes:**
1. Set `LOGIN_URL = "/login/"` in settings
2. Set `PARENT_HOST = "example.com"` for proper URL generation
3. Add redirect from `/admin/` to `/` in admin_urls.py

## Key Points
- Admin served at admin.example.com/ (root)
- Login at admin.example.com/login/ (NOT /admin/login/)
- PARENT_HOST required for django-hosts URL generation
- Redirect /admin/ to / prevents old URL loops

## Allowed Hosts
```python
ALLOWED_HOSTS = [".example.com"]  # All subdomains
```

## URL Generation
```python
from django_hosts.resolvers import reverse
admin_url = reverse("admin:index", host="admin")
# → https://admin.example.com/
```
Created December 19, 2025 • Last updated December 20, 2025 • Public

Discussion 0

Login to join the discussion.
Keep Comments Focused

This snippet is optimized for AI models. Please keep comments constructive and relevant—suggest improvements, report issues, or ask clarifying questions. Excessive off-topic discussion may reduce the snippet's effectiveness for AI parsing.

No comments yet. Be the first to share your thoughts!