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.