How can I get the full/absolute URL (with domain) in Django?
How can I get the full/absolute URL (e.g. https://example.com/some/path
) in Django without the Sites module? That's just silly... I shouldn't need to query my DB to snag the URL!
I want to use it with reverse()
.
Use handy request.build_absolute_uri() method on request, pass it the relative url and it'll give you full one.
By default, the absolute URL for request.get_full_path()
is returned, but you can pass it a relative URL as the first argument to convert it to an absolute URL.
If you want to use it with reverse()
you can do this : request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))
If you can't get access to request
then you can't use get_current_site(request)
as recommended in some solutions here. You can use a combination of the native Sites framework and get_absolute_url
instead. Set up at least one Site in the admin, make sure your model has a get_absolute_url() method, then:
>>> from django.contrib.sites.models import Site
>>> domain = Site.objects.get_current().domain
>>> obj = MyModel.objects.get(id=3)
>>> path = obj.get_absolute_url()
>>> url = 'http://{domain}{path}'.format(domain=domain, path=path)
>>> print(url)
'http://example.com/mymodel/objects/3/'
https://docs.djangoproject.com/en/dev/ref/contrib/sites/#getting-the-current-domain-for-full-urls
You can also use get_current_site
as part of the sites app (from django.contrib.sites.models import get_current_site
). It takes a request object, and defaults to the site object you have configured with SITE_ID
in settings.py if request is None
. Read more in documentation for using the sites framework
e.g.
from django.contrib.sites.shortcuts import get_current_site
request = None
full_url = ''.join(['http://', get_current_site(request).domain, obj.get_absolute_url()])
It isn't as compact/neat as request.build_absolute_url()
, but it is usable when request objects are unavailable, and you have a default site url.
If you don't want to hit the database, you could do it with a setting. Then, use a context processor to add it to every template:
# settings.py (Django < 1.9)
...
BASE_URL = 'http://example.com'
TEMPLATE_CONTEXT_PROCESSORS = (
...
'myapp.context_processors.extra_context',
)
# settings.py (Django >= 1.9)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
# Additional
'myapp.context_processors.extra_context',
],
},
},
]
# myapp/context_processors.py
from django.conf import settings
def extra_context(request):
return {'base_url': settings.BASE_URL}
# my_template.html
<p>Base url is {{ base_url }}.</p>