django-hosts

https://img.shields.io/pypi/v/django-hosts.svg https://img.shields.io/travis/jazzband/django-hosts.svg https://img.shields.io/coveralls/jazzband/django-hosts.svg https://readthedocs.org/projects/django-hosts/badge/?version=latest&style=flat https://jazzband.co/static/img/badge.svg

This Django app routes requests for specific hosts to different URL schemes defined in modules called “hostconfs”.

For example, if you own example.com but want to serve specific content at api.example.com and beta.example.com, add the following to a hosts.py file:

from django_hosts import patterns, host

host_patterns = patterns('path.to',
    host(r'api', 'api.urls', name='api'),
    host(r'beta', 'beta.urls', name='beta'),
)

This causes requests to {api,beta}.example.com to be routed to their corresponding URLconf. You can use your urls.py as a template for these hostconfs.

Patterns are evaluated in order. If no pattern matches, the request is processed in the usual way, ie. using the standard ROOT_URLCONF.

The patterns on the left-hand side are regular expressions. For example, the following ROOT_HOSTCONF setting will route foo.example.com and bar.example.com to the same URLconf.

from django_hosts import patterns, host

host_patterns = patterns('',
    host(r'(foo|bar)', 'path.to.urls', name='foo-or-bar'),
)

Installation

First, install the app with your favorite package manager, e.g.:

pip install django-hosts

Alternatively, use the repository on Github.

You can find the full docs here: django-hosts.rtfd.org

Then configure your Django site to use the app:

  1. Add 'django_hosts' to your INSTALLED_APPS setting.

  2. Add 'django_hosts.middleware.HostsRequestMiddleware' to the beginning of your MIDDLEWARE or MIDDLEWARE_CLASSES setting.

  3. Add 'django_hosts.middleware.HostsResponseMiddleware' to the end of your MIDDLEWARE or MIDDLEWARE_CLASSES setting.

  4. Create a new module containing your default host patterns, e.g. in the hosts.py file next to your urls.py.

  5. Set the ROOT_HOSTCONF setting to the dotted Python import path of the module containing your host patterns, e.g.:

    ROOT_HOSTCONF = 'mysite.hosts'
    
  6. Set the DEFAULT_HOST setting to the name of the host pattern you want to refer to as the default pattern. It’ll be used if no other pattern matches or you don’t give a name to the host_url template tag.

Usage

Patterns being regular expressions allows setups to feature dynamic (or “wildcard”) host schemes:

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

host_patterns = patterns('',
    host(r'www', settings.ROOT_URLCONF, name='www'),
    host(r'(\w+)', 'path.to.custom_urls', name='wildcard'),
)

Here, requests to www.example.com will be routed as normal but a request to admin.example.com is routed to path.to.custom_urls.

As patterns are matched in order, we placed www first as it otherwise would have matched against \w+ and thus routed to the wrong destination.

Alternatively, we could have used negative lookahead, given the value of the ROOT_URLCONF setting:

from django_hosts import patterns, host

host_patterns = patterns('',
    host(r'(?!www)\w+', 'path.to.custom_urls', name='wildcard'),
)

In your templates you can use the host_url() template tag to reverse a URL the way you’re used to it with Django’s url template tag:

{% load hosts %}
<a href="{% host_url 'homepage' host 'www' %}">Home</a> |
<a href="{% host_url 'account' host 'wildcard' request.user.username %}">Your Account</a> |

Since the template tag will always automatically fall back to your default host (as defined by DEFAULT_HOST) you can leave off the host parameter as well.

You can even override the url tag that comes with Django to simplify reversing URLs in your templates:

<a href="{% url 'homepage' %}">Home</a> |
<a href="{% url 'account' host 'wildcard' request.user.username %}">Your Account</a> |

On the Python side of things like your views you can easily do the same as with Django’s own reverse function. Simply use the reverse() function for that:

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})

Settings

django.conf.settings.ROOT_HOSTCONF(required)

The dotted Python import path of the module containing your host patterns. Similar to ROOT_URLCONF.

django.conf.settings.DEFAULT_HOST(required)

The name of the host pattern you want to refer to as the default pattern. Used if no other host pattern matches or no host name is passed to the host_url() template tag.

django.conf.settings.PARENT_HOST(optional)

The parent domain name to be appended to the reversed domain (e.g. using the host_url() template tag).

django.conf.settings.HOST_SCHEME(optional)

The scheme to prepend host names with during reversing, e.g. when using the host_url() template tag. Defaults to '//'.

django.conf.settings.HOST_PORT(optional)

New in version 1.0.

The port to append to host names during reversing, e.g. when using the host_url() template tag. Defaults to '' (empty string).

django.conf.settings.HOST_SITE_TIMEOUT(optional)

The time to cache the host in the default cache backend, in seconds, when using the cached_host_site() callback. Defaults to 3600.

django.conf.settings.HOST_OVERRIDE_URL_TAG(optional)

New in version 1.0.

Whether or not to automatically override Django’s default url template tag. Defaults to False.

On Django 1.9+, you must add 'django_hosts.templatetags.hosts_override' to the TEMPLATES['OPTIONS']['builtins'] list instead of using this setting.

Issues

For any bug reports and feature requests, please use the Github issue tracker.

Thanks

Many thanks to the folks at playfire for releasing their django-dynamic-subdomains app, which was the inspiration for this app.