Comment puis-je obtenir le nom de domaine de mon site actuel à partir d'un modèle Django? J'ai essayé de regarder dans l'étiquette et les filtres mais rien là-bas.
Je pense que ce que vous voulez, c'est avoir accès au contexte de la requête, voir RequestContext.
Si vous voulez l'en-tête de l'hôte HTTP, voir le commentaire de Daniel Roseman sur la réponse de @ Phsiao. L’autre alternative est que, si vous utilisez le cadre contrib.sites , vous pouvez définir un nom de domaine canonique pour un site dans la base de données faites vous-même via la configuration de votre serveur web). Dans ce cas, vous recherchez:
from Django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
vous devez vous-même placer l'objet current_site dans un contexte de modèle si vous souhaitez l'utiliser. Si vous l'utilisez partout, vous pouvez l'intégrer dans un processeur de modèle de contexte.
J'ai découvert la méthode {{ request.get_Host }}
.
En complément de Carl Meyer, vous pouvez créer un processeur de contexte comme ceci:
from Django.conf import settings
def site(request):
return {'SITE_URL': settings.SITE_URL}
SITE_URL = 'http://google.com' # this will reduce the Sites framework db call.
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
vous pouvez écrire votre propre rutine si vous voulez gérer des sous-domaines ou SSL dans le processeur de contexte.
La variation du processeur de contexte que j'utilise est la suivante:
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)),
}
Le wrapper SimpleLazyObject
s'assure que l'appel de base de données ne se produit que lorsque le modèle utilise réellement l'objet site
Cela supprime la requête des pages d'administration. Il met également en cache le résultat.
et l'inclure dans les paramètres:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
Dans le modèle, vous pouvez utiliser {{ site.domain }}
pour obtenir le nom de domaine actuel.
edit: pour supporter aussi la commutation de protocole, utilisez:
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)),
}
Je sais que cette question est ancienne, mais je suis tombé sur elle à la recherche d'un moyen pythonique pour obtenir le domaine actuel.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
Rapide et simple, mais pas bon pour la production:
(dans une vue)
request.scheme # http or https
request.META['HTTP_Host'] # example.com
request.path # /some/content/1/
(dans un modèle)
{{ request.scheme }} :// {{ request.META.HTTP_Host }} {{ request.path }}
Veillez à utiliser un RequestContext , ce qui est le cas si vous utilisez render .
Ne faites pas confiance à request.META['HTTP_Host']
en production: cette information provient du navigateur. Au lieu de cela, utilisez la réponse de @ CarlMeyer
{{ request.get_Host }}
devrait protéger contre les attaques d'en-tête d'hôte HTTP lorsqu'il est utilisé avec le paramètre ALLOWED_HOSTS
(ajouté dans Django 1.4.4).
Notez que {{ request.META.HTTP_Host }}
n'a pas la même protection. Voir le docs :
ALLOWED_HOSTS
Une liste de chaînes représentant les noms d'hôte/de domaine que ce site Django peut servir. Il s'agit d'une mesure de sécurité visant à empêcher les attaques par en-tête d'hôte HTTP , qui sont possibles même avec de nombreuses configurations de serveur Web apparemment sûres.
... Si l'en-tête
Host
(ouX-Forwarded-Host
siUSE_X_FORWARDED_Host
est activé) ne correspond à aucune valeur de cette liste, la méthodeDjango.http.HttpRequest.get_Host()
lèveraSuspiciousOperation
.... Cette validation ne s'applique que via
get_Host()
; Si votre code accède à l'en-tête de l'hôte directement à partir derequest.META
, vous contournez cette protection de sécurité.
En ce qui concerne l'utilisation de request
dans votre modèle, les appels de fonction de rendu de modèle ont modifié dans Django 1.8 , de sorte que vous n'avez plus à gérer directement RequestContext
.
Voici comment rendre un modèle pour une vue à l'aide de la fonction de raccourci render()
:
from Django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
Voici comment rendre un modèle pour un courrier électronique. Dans le meilleur des cas, vous souhaitez obtenir la valeur de l'hôte:
from Django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
Voici un exemple d’ajout d’une URL complète dans un modèle de courrier électronique; request.scheme devrait obtenir http
ou https
selon ce que vous utilisez:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_Host }}{% url 'registration_activate' activation_key %}
J'utilise une balise de modèle personnalisé. Ajouter à, par exemple <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
Utilisez-le dans un modèle comme celui-ci:
{% load site %}
{% current_domain %}
Semblable à la réponse de l'utilisateur panchicore, voici ce que j'ai fait sur un site Web très simple… .. Il fournit quelques variables et les rend disponibles sur le modèle.
SITE_URL
aurait une valeur comme example.com
SITE_PROTOCOL
aurait une valeur comme http
ou https
SITE_PROTOCOL_URL
aurait une valeur comme http://example.com
ou https://example.com
SITE_PROTOCOL_RELATIVE_URL
aurait une valeur comme //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'
Ensuite, sur vos modèles, utilisez-les comme {{ SITE_URL }}
, {{ SITE_PROTOCOL }}
, {{ SITE_PROTOCOL_URL }}
et {{ SITE_PROTOCOL_RELATIVE_URL }}
Dans un modèle Django, vous pouvez faire:
<a href="{{ request.scheme }}://{{ request.META.HTTP_Host }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
from Django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
Qu'en est-il de cette approche? Fonctionne pour moi . Il est également utilisé dans 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)