How can I get the domain name of my site within a Django template?

Viewed 196238

How do I get the domain name of my current site from within a Django template? I've tried looking in the tag and filters but nothing there.

19 Answers

If you use the "request" context processor, and are using the Django sites framework, and have the Site middleware installed (i.e. your settings include these):

INSTALLED_APPS = [
    ...
    "django.contrib.sites",
    ...
]

MIDDLEWARE = [
    ...
     "django.contrib.sites.middleware.CurrentSiteMiddleware",
    ...
]

... then you will have the request object available in templates, and it will contain a reference to the current Site for the request as request.site. You can then retrieve the domain in a template with:

    {{request.site.domain}}

and the site name with:

    {{request.site.name}}

In a Django template you can do:

<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>

You can use request.build_absolute_uri()

By default, it will return a full path.

But if you pass in a parameter like this:

request.build_absolute_uri('/')

This would return the domain name.

I figure what we want is an alternative to the existing url tag, so I wrote a new tag:

from django.template import Library
from django.urls     import reverse

@register.simple_tag(takes_context = True)
def fullURL(context, name, *args, **kwargs):
    request = context['request']
    return f'{request.scheme}://{request.get_host()}{reverse(name, args = args, kwargs = kwargs)}'

Then in your template you can have this...

{% extends "myapp/email/email_base.html" %}

{% load mytags %} {# Replace mytags with whatever the name of your custom tags calss is. #}

{% block content %}
<p>You can use <a href="{% fullURL 'signup' %}">this link</a> to get started with your account. We look forward to seeing you soon!</p>
{% endblock content %}

Then when you generate this, you just need to remember to pass the request into the context, like so...

from django.template.loader import render_to_string

def sendEmail(subject, to, template, **context):
    html = render_to_string(f'myapp/email/{template}.html', context | {'subject': subject})
    # ... and so on with the rest of my function for sending email...

As alluded to in @furins response there may be issues with proxy servers. I found this myself when using Apache and uWSGI – request.get_host or request.build_absolute_uri would return the proxy host (127.0.0.1:9191…).

However, someone has helpfully posted a guide to fixing this:

https://ubuntu.com/blog/django-behind-a-proxy-fixing-absolute-urls

Although this is a relatively old answer, it is still relevant to django 3.2 and python 3.9.

Just in case the answer disappears in the future, here is the gist of it:

settings.py

# Setup support for proxy headers
USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

apache.conf

<VirtualHost *:443>
    ...
    RequestHeader set X-Forwarded-Proto 'https' env=HTTPS

    ProxyPass / http://10.0.0.3/
    ProxyPassReverse / http://10.0.0.3/
    ...
</VirtualHost>

With these settings request.get_host and request.build_absolute_uri reference the client requested host and not the proxy host.

These below can get a full url and parts of url:

def myview(request):
    request.build_absolute_uri()
    # http://localhost:8000/admin/store/product/

    request.build_absolute_uri('/')
    # http://localhost:8000/

    request.build_absolute_uri('/')[:-1]
    # http://localhost:8000

    request.scheme
    # http

    request.META['HTTP_HOST']
    # localhost:8000

    request.path    
    # /admin/store/product/
Related