django-subdomains2
django-subdomains2 is a fork of the no longer managed django-subdomain repo.
Tested on Python 3.8, 3.9, 3.10 and Django 3.2, 4.0
Installation
pip install django-subdomains2
Quick Start
-
Add subdomains.middleware.SubdomainURLRoutingMiddleware
to your MIDDLEWARE
in your Django settings file. If you are using django.middleware.common.CommonMiddleware
, the subdomain middlware should come before CommonMiddleware
MIDDLEWARE = [
...
"subdomains.middleware.SubdomainURLRoutingMiddleware",
"django.middleware.common.CommonMiddleware",
...
]
-
Configure the SUBDOMAIN_URLCONFS
dictionary in Django settings file.
ROOT_URLCONF = "myproject.urls.frontend"
SUBDOMAIN_URLCONFS = {
None: "myproject.urls.frontend",
"www": "myproject.urls.frontend",
"api": "myproject.urls.api",
"admin": "myproject.urls.admin",
}
-
Configure the SUBDOMAIN_DOMAIN
in Django settings file.
SUBDOMAIN_DOMAIN = "mysite.com"
SUBDOMAIN_IGNORE_HOSTS = ["health-check"]
Optional - SUBDOMAIN_IGNORE_HOSTS
Add hosts to SUBDOMAIN_IGNORE_HOSTS
if you need a list of hosts not to search for subdomains (which automatically uses the "None" value of SUBDOMAIN_URLCONFS)
-
If you want to use the subdomain-based {% url %}
template tag, add subdomains
to your INSTALLED_APPS
.
Basic Usage
Using Subdomains in Views
On each request, a subdomain
attribute will be added to the request
object. You can use this attribute to effect view logic, like in this example:
def user_profile(request):
try:
user = User.objects.get(username=request.subdomain)
except User.DoesNotExist:
raise Http404
Resolving Named URLs by Subdomain
Included is a subdomains.utils.reverse()
function that responds similarly to django.core.urlresolvers.reverse()
, but accepts optional subdomain
and scheme
arguments and does not allow a urlconf
parameter.
If no subdomain
argument is provided, the URL will be resolved relative to the SUBDOMAIN_URLCONFS[None]
or ROOT_URLCONF
, in order. The protocol scheme is the value of settings.DEFAULT_URL_SCHEME
, or if unset, http
:
>>> from subdomains.utils import reverse
>>> reverse('home')
'http://example.com/'
>>> reverse('user-profile', kwargs={'username': 'ted'})
'http://example.com/users/ted/'
>>> reverse('home', scheme='https')
'https://example.com/'
For subdomains, the URL will be resolved relative to the SUBDOMAIN_URLCONFS[subdomain]
value if it exists, otherwise falling back to the ROOT_URLCONF
:
>>> from subdomains.utils import reverse
>>> reverse('home', subdomain='api')
'http://api.example.com/'
>>> reverse('home', subdomain='wildcard')
'http://wildcard.example.com/'
>>> reverse('login', subdomain='wildcard')
'http://wildcard.example.com/login/'
If a URL cannot be resolved, a django.urls.exceptions.NoReverseMatch
will be raised.
Resolving Named URLs in Templates
The subdomainurls
template tag library contains a url
tag that takes an optional subdomain
argument as it’s first positional argument, or as named argument. The following are all valid invocations of the tag:
{% load subdomainurls %}
{% url 'home' %}
{% url 'home' 'subdomain' %}
{% url 'home' subdomain='subdomain' %}
{% url 'user-profile' username='ted' %}
{% url 'user-profile' subdomain='subdomain' username='ted' %}
If request
is in the template context when rendering and no subdomain is provided, the URL will be attempt to be resolved by relative to the current subdomain. If no request is available, the URL will be resolved using the same rules as a call to subdomains.utils.reverse()
without a subdomain
argument value. An easy way to ensure this functionality is available is to add django.core.context_processors.request()
is in your settings.TEMPLATES["OPTIONS"]["context_processors"]
list.
Test
tox
Deploy
pip install build setuptools wheel
python -m build
twine upload dist/*