Configuring and setting up subdomains on Django using django-hosts
A subdomain is basically a domain that’s part of another main domain and it is used a lot in many websites. I spent a decent amount of time figuring out how to do that and found this very helpful post and decided to extend it a little in a tutorial form. So if you ever want to add a subdomain for your Django site, something like subdomain.your-site.com
, this might help.
We are going to go through all the steps from creating a project in django, to getting our subdomain up and running.
Create a Python virtual environment
As a best practice, we will create a virtual environment. I will use conda here to create it with a specific version of python.
$ conda create -n django-env python=3.6
$ conda activate django-env
Packages installation
Now let’s use pip to install Django [3] and django-hosts [4]:
$ pip install django django-hosts
Create a Django project and app
Once installed, let’s go to our workspace directory and create our django project:
$ django-admin startproject simpletest
You will see a new directory created named simpletest
and inside it, a manage.py
file and another simpletest
folder. To avoid confusion between the project and our apps, I like to rename the parent folder so l’ll just call it simpletest-prj
. Now you will have something like this:
simpletest-prj
├── manage.py
└── simpletest
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
Let’s move inside our simpletest
directory to run python3 manage.py runserver
and open http://localhost:8000/ to make sure our project works. You should get a page like this.
Now stop your application and create a new app that we will call home
:
$ python3 manage.py startapp home
We now want to put our own homepage instead of the django default landing page by following a few steps:
First we need to add a new line to the urls.py
file in simpletest
under the admin url so that Django knows where to look and redirect when opening our site:
from django.contrib import admin
from django.urls import path
from . import views # <-- new import
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.home), # <-- new line
]
Then we need to create a views.py
file under the simpletest
folder with the following code. This is the one with the logic, but now we will only render and return a home.html
file:
from django.shortcuts import render
def home(request):
return render(request, 'home.html')
The next thing is to create a template folder under the main project directory simpletest-prj
and our home.html
file with the following content:
<html>
<head>
<title>Welcome!</title>
</head>
<body>
Hello there, and welcome to my new site.
</body>
</html>
Finally, we need to create our TEMPLATE_DIR
variable and add it to the TEMPLATES
structure on the settings.py
file:
import os
# Right below the BASE_DIR declaration
TEMPLATE_DIR = os.path.join(BASE_DIR, 'templates')
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATE_DIR,], # <-- This is the modified line
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Refresh your page or run it one more time to get the expected result:
Our directory structure will now look like this:
simpletest-prj
├── db.sqlite3
├── home
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── manage.py
├── simpletest
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
└── templates
└── home.html
Configure the app with subdomain
So now our main page is located at localhost:8000
and what we like to do is to host our home
app on home.localhost:8000
instead of something like localhost:8000/home
. For that we will do the following:
We need to add home
to our app list along with the already installed django-hosts
in the settings.py
file:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'home', # <-- Add this
'django_hosts', # <-- and this
]
Then let’s add our hosts to the ALLOWED_HOSTS
variable in the same file:
ALLOWED_HOSTS = ['localhost', 'home.localhost']
The MIDDLEWARE
variable needs to be updated with the following two values, the first one at the beginning and the second one at the end
'django_hosts.middleware.HostsRequestMiddleware'
'django_hosts.middleware.HostsResponseMiddleware'
MIDDLEWARE = [
'django_hosts.middleware.HostsRequestMiddleware', # <-- new line
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django_hosts.middleware.HostsResponseMiddleware', # <-- another new line
]
Under the ROOT_URLCONF
line, add the following:
ROOT_HOSTCONF = 'simpletest.hosts'
DEFAULT_HOST = 'www'
And now we create a hosts.py
file under simpletest
. This file will contain all the list of subdomains that will be on our site:
from django_hosts import patterns, host
from django.conf import settings
host_patterns = patterns(
'',
host(r'www', settings.ROOT_URLCONF, name='www'),
host(r'home', 'home.urls', name='home')
)
So now we go on to create and edit a urls.py
file under the home
directory:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.home, name='home'),
]
And create our view in its corresponding views.py
file:
from django.shortcuts import render
def home(request):
return render(request, 'home/hello.html')
Create a templates
folder under home
with another home
subdirectory and a hello.html
file inside:
<html>
<head>
<title>Home</title>
</head>
<body>
Welcome to the subdomain homepage!
</body>
</html>
Save all, refresh your application or run it one more time, and now go to http://home.localhost:8000/
For reference, the directory structure should look something like the following at this point:
simpletest-prj
├── db.sqlite3
├── home
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── templates
│ │ └── home
│ │ └── hello.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── manage.py
├── simpletest
│ ├── __init__.py
│ ├── asgi.py
│ ├── hosts.py
│ ├── settings.py
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
└── templates
└── home.html
And that would be it! When you’re ready to deploy your application on your configured domain, just make sure you edit the ALLOWED_HOSTS
variable to match the name of the actual domain.
Subscribe to my newsletter
Read articles from Miguel Ángel directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Miguel Ángel
Miguel Ángel
Software Engineer that works mainly with Go and Python. Loves music and beer.