PageView

How to Use django-hosts Library

How to Use django-hosts Library

This is a very handy Django package that I’ve used in a couple of projects. Essentially django-hosts let you serve different parts of your application under different subdomains. For example, let’s say we have a Django application deployed on www.example.com. With this app you can serve an e-commerce under shop.example.com and the help center under help.example.com. And in the end, it’s just a single Django website.

It can also be used to host user spaces, with a wildcard, where your users could get their own subdomain like vitor.example.com or erica.example.com. But that require a few tweaks in the DNS configuration.

A small caveat of developing with django-hosts is that you will need to do some configurations in your local machine, which can differ if you are using Windows, Linux or Mac.


Installation

Install it with pip:

pip install django-hosts

Add the django_hosts to the INSTALLED_APPS:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'django_hosts',

    'core',
]

Add the HostsRequestMiddleware in the beginning of the MIDDLEWARE and HostsResponseMiddleware in the end of the MIDDLEWARE:

MIDDLEWARE = [
    'django_hosts.middleware.HostsRequestMiddleware',

    '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',
]

Still in the settings.py, add the following configuration variables:

ROOT_HOSTCONF = 'mysite.hosts'  # Change `mysite` to the name of your project
DEFAULT_HOST = 'www'  # Name of the default host, we will create it in the next steps

Create a file named hosts.py right next to the urls.py:

mysite/
 |-- __init__.py
 |-- hosts.py  # <-- The `ROOT_HOSTCONF` refers to this file
 |-- settings.py
 |-- urls.py
 +-- wsgi.py

mysite/hosts.py

from django.conf import settings
from django_hosts import patterns, host

host_patterns = patterns('',
    host(r'www', settings.ROOT_URLCONF, name='www'),  # <-- The `name` we used to in the `DEFAULT_HOST` setting
)

Usage

Let’s create an app named help to illustrate the usage of the django-hosts:

django-admin startapp help

Then inside of the new app, we create a urls.py module:

help/urls.py

from django.conf.urls import url, include

from . import views

urlpatterns = [
    url(r'^$', views.home, name='home'),
    url(r'^articles/$', views.articles, name='articles'),
    url(r'^articles/(?P<pk>\d+)/$', views.article_details, name='article_details'),
]

Now we update the mysite/hosts, which is our ROOT_HOSTCONF:

mysite/hosts.py

from django.conf import settings
from django_hosts import patterns, host

host_patterns = patterns('',
    host(r'www', settings.ROOT_URLCONF, name='www'),
    host(r'help', 'help.urls', name='help'),
)

Testing Locally

In order to test it locally, you will need to setup a local DNS host.

On Linux and Mac, the file is located in the path /etc/hosts. For Windows it should be somewhere in %SystemRoot%\system32\drivers\etc\hosts.

hosts

127.0.0.1 localhost
255.255.255.255 broadcasthost
::1             localhost

127.0.0.1 www.mysite.local
127.0.0.1 help.mysite.local
Django Hosts Help Site
Django Hosts My Site

Templates

Now instead of using the {% url 'home' %} notation, you can load the django-hosts template tags:

{% load hosts %}

<a href="{% host_url 'home' host 'www' %}">Homepage</a>
<a href="{% host_url 'articles' host 'help' %}">Help Articles</a>

Reverse

The django-hosts extends Django’s default reverse function so you can pass an extra argument host:

from django.shortcuts import render
from django_hosts.resolvers import reverse

def homepage(request):
    homepage_url = reverse('homepage', host='www')
    return render(request, 'homepage.html', {'homepage_url': homepage_url})

Further Reading

You can learn more by reading the Official Documentation or browsing the code on GitHub.