135👍
If you want the actual HTTP Host header, see Daniel Roseman’s comment on @Phsiao’s answer. The other alternative is if you’re using the contrib.sites framework, you can set a canonical domain name for a Site in the database (mapping the request domain to a settings file with the proper SITE_ID is something you have to do yourself via your webserver setup). In that case you’re looking for:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
you’d have to put the current_site object into a template context yourself if you want to use it. If you’re using it all over the place, you could package that up in a template context processor.
- [Django]-Copy a database column into another in Django
- [Django]-Django py.test does not find settings module
- [Django]-Django Template Language: Using a for loop with else
- [Django]-How to change site title, site header and index title in Django Admin?
- [Django]-Django – iterate number in for loop of a template
- [Django]-*_set attributes on Django Models
70👍
Complementing Carl Meyer, you can make a context processor like this:
module.context_processors.py
from django.conf import settings
def site(request):
return {'SITE_URL': settings.SITE_URL}
local settings.py
SITE_URL = 'http://google.com' # this will reduce the Sites framework db call.
settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
templates returning context instance the url site is {{ SITE_URL }}
you can write your own rutine if want to handle subdomains or SSL in the context processor.
- [Django]-Where can I find the error logs of nginx, using FastCGI and Django?
- [Django]-How can I chain Django's "in" and "iexact" queryset field lookups?
- [Django]-Warning: Auto-created primary key used when not defining a primary key type, by default 'django.db.models.AutoField'
34👍
I know this question is old, but I stumbled upon it looking for a pythonic way to get current domain.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
- [Django]-Where is a good place to work on accounts/profile in Django with the Django registration app?
- [Django]-Naming convention for Django URL, templates, models and views
- [Django]-Row level permissions in django
33👍
Quick and simple, but not good for production:
(in a view)
request.scheme # http or https
request.META['HTTP_HOST'] # example.com
request.path # /some/content/1/
(in a template)
{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
Be sure to use a RequestContext, which is the case if you’re using render.
Don’t trust request.META['HTTP_HOST']
in production: that info comes from the browser. Instead, use @CarlMeyer’s answer
- [Django]-Django self-referential foreign key
- [Django]-Django admin and MongoDB, possible at all?
- [Django]-How to disable admin-style browsable interface of django-rest-framework?
29👍
{{ request.get_host }}
should protect against HTTP Host header attacks when used together with the ALLOWED_HOSTS
setting (added in Django 1.4.4).
Note that {{ request.META.HTTP_HOST }}
does not have the same protection. See the docs:
ALLOWED_HOSTS
A list of strings representing the host/domain names that this Django site can serve. This is a security measure to prevent HTTP Host header attacks, which are possible even under many seemingly-safe web server configurations.
… If the
Host
header (orX-Forwarded-Host
ifUSE_X_FORWARDED_HOST
is enabled) does not match any value in this list, thedjango.http.HttpRequest.get_host()
method will raiseSuspiciousOperation
.… This validation only applies via
get_host()
; if your code accesses the Host header directly fromrequest.META
you are bypassing this security protection.
As for using the request
in your template, the template-rendering function calls have changed in Django 1.8, so you no longer have to handle RequestContext
directly.
Here’s how to render a template for a view, using the shortcut function render()
:
from django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
Here’s how to render a template for an email, which IMO is the more common case where you’d want the host value:
from django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
Here’s an example of adding a full URL in an email template; request.scheme should get http
or https
depending on what you’re using:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
- [Django]-Why won't Django use IPython?
- [Django]-Django Rest Framework Conditional Field on Serializer
- [Django]-Django.contrib.gis.db.backends.postgis vs django.db.backends.postgresql_psycopg2
26👍
The variation of the context processor I use is:
from django.contrib.sites.shortcuts import get_current_site
from django.utils.functional import SimpleLazyObject
def site(request):
return {
'site': SimpleLazyObject(lambda: get_current_site(request)),
}
The SimpleLazyObject
wrapper makes sure the DB call only happens when the template actually uses the site
object. This removes the query from the admin pages. It also caches the result.
and include it in the settings:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
In the template, you can use {{ site.domain }}
to get the current domain name.
edit: to support protocol switching too, use:
def site(request):
site = SimpleLazyObject(lambda: get_current_site(request))
protocol = 'https' if request.is_secure() else 'http'
return {
'site': site,
'site_root': SimpleLazyObject(lambda: "{0}://{1}".format(protocol, site.domain)),
}
- [Django]-How to execute a Python script from the Django shell?
- [Django]-How to specify an IP address with Django test client?
- [Django]-How to add a cancel button to DeleteView in django
10👍
I use a custom template tag. Add to e.g. <your_app>/templatetags/site.py
:
# -*- coding: utf-8 -*-
from django import template
from django.contrib.sites.models import Site
register = template.Library()
@register.simple_tag
def current_domain():
return 'http://%s' % Site.objects.get_current().domain
Use it in a template like this:
{% load site %}
{% current_domain %}
- [Django]-Django template how to look up a dictionary value with a variable
- [Django]-Google Static Maps URL length limit
- [Django]-Check if celery beat is up and running
9👍
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}}
- [Django]-Homepage login form Django
- [Django]-Allowing only super user login
- [Django]-Checking for empty queryset in Django
6👍
Similar to user panchicore’s reply, this is what I did on a very simple website.
It provides a few variables and makes them available on the template.
SITE_URL
would hold a value like example.com
SITE_PROTOCOL
would hold a value like http
or https
SITE_PROTOCOL_URL
would hold a value like http://example.com
or https://example.com
SITE_PROTOCOL_RELATIVE_URL
would hold a value like //example.com
.
module/context_processors.py
from django.conf import settings
def site(request):
SITE_PROTOCOL_RELATIVE_URL = '//' + settings.SITE_URL
SITE_PROTOCOL = 'http'
if request.is_secure():
SITE_PROTOCOL = 'https'
SITE_PROTOCOL_URL = SITE_PROTOCOL + '://' + settings.SITE_URL
return {
'SITE_URL': settings.SITE_URL,
'SITE_PROTOCOL': SITE_PROTOCOL,
'SITE_PROTOCOL_URL': SITE_PROTOCOL_URL,
'SITE_PROTOCOL_RELATIVE_URL': SITE_PROTOCOL_RELATIVE_URL
}
settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
SITE_URL = 'example.com'
Then, on your templates, use them as {{ SITE_URL }}
, {{ SITE_PROTOCOL }}
, {{ SITE_PROTOCOL_URL }}
and {{ SITE_PROTOCOL_RELATIVE_URL }}
- [Django]-No handlers could be found for logger
- [Django]-Django – getting Error "Reverse for 'detail' with no arguments not found. 1 pattern(s) tried:" when using {% url "music:fav" %}
- [Django]-Sending post data from angularjs to django as JSON and not as raw content
6👍
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.
- [Django]-How can I access environment variables directly in a Django template?
- [Django]-How to define two fields "unique" as couple
- [Django]-Google Static Maps URL length limit
4👍
In a Django template you can do:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
- [Django]-What is pip install -q -e . for in this Travis-CI build tutorial?
- [Django]-Best practices for adding .gitignore file for Python projects?
- [Django]-Django – Rotating File Handler stuck when file is equal to maxBytes
1👍
What about this approach? Works for me.
It is also used in django-registration.
def get_request_root_url(self):
scheme = 'https' if self.request.is_secure() else 'http'
site = get_current_site(self.request)
return '%s://%s' % (scheme, site)
- [Django]-Resource temporarily unavailable using uwsgi + nginx
- [Django]-What is pip install -q -e . for in this Travis-CI build tutorial?
- [Django]-Django substr / substring in templates
1👍
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...
- [Django]-Django fix Admin plural
- [Django]-Django-social-auth django-registration and django-profiles — together
- [Django]-How do I clone a Django model instance object and save it to the database?
1👍
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.
- [Django]-How do you dynamically hide form fields in Django?
- [Django]-Unittest Django: Mock external API, what is proper way?
- [Django]-Python Asyncio in Django View
1👍
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/
- [Django]-What's the idiomatic Python equivalent to Django's 'regroup' template tag?
- [Django]-Is there a list of Pytz Timezones?
- [Django]-No module named pkg_resources
0👍
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
- [Django]-How can I upgrade specific packages using pip and a requirements file?
- [Django]-How do I match the question mark character in a Django URL?
- [Django]-Naming convention for Django URL, templates, models and views
- [Django]-Django: Reverse for 'detail' with arguments '('',)' and keyword arguments '{}' not found
- [Django]-CORS: Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true
- [Django]-How do you change the collation type for a MySQL column?