Comment obtenir le nom de domaine de mon site actuel à partir d'un modèle Django ? J'ai essayé de regarder dans la balise et les filtres mais rien n'y fait.
Réponses
Trop de publicités?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 l'application Rendu .
Ne pas faire confiance request.META['HTTP_HOST']
en production : cette information provient du navigateur. Utilisez plutôt la réponse de @CarlMeyer
La variation du processeur contextuel 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 site SimpleLazyObject
permet de s'assurer que l'appel à la base de données n'a lieu que lorsque le modèle utilise effectivement la fonction site
objet. Cela supprime la requête des pages d'administration. Elle 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.
éditer : pour supporter la commutation de protocole aussi, 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)),
}
{{ request.get_host }}
devrait protéger contre les attaques de l'en-tête HTTP Host lorsqu'elle est utilisée avec l'option ALLOWED_HOSTS
(ajouté dans Django 1.4.4).
Notez que {{ request.META.HTTP_HOST }}
ne bénéficie pas de la même protection. Voir le docs :
HÔTES AUTORISÉS
Une liste de chaînes représentant les noms d'hôte/domaine que ce site Django peut servir. Il s'agit d'une mesure de sécurité visant à empêcher Attaques contre l'en-tête d'hôte HTTP qui sont possibles même dans de nombreuses configurations de serveurs web apparemment sûres.
... Si le
Host
(ouX-Forwarded-Host
siUSE_X_FORWARDED_HOST
est activé) ne correspond à aucune valeur de cette liste, l'optiondjango.http.HttpRequest.get_host()
soulèveraSuspiciousOperation
.... Cette validation ne s'applique que via
get_host()
; si votre code accède à l'en-tête Host directement à partir derequest.META
vous contournez cette protection de sécurité.
Quant à l'utilisation de la request
dans votre modèle, les appels de fonction de rendu de modèle ont modifié dans Django 1.8 pour que vous n'ayez plus à vous occuper RequestContext
directement.
Voici comment rendre un modèle pour une vue, en utilisant la fonction raccourcie 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 courriel, ce qui, à mon avis, est le cas le plus courant où vous voulez 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 d'e-mail ; schéma de la demande devrait obtenir http
o https
en fonction de 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ée. Ajouter à par ex. <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 %}
Si vous utilisez le processeur de contexte "request" (demande) et utilisent le Cadre des sites Django et avoir le Middleware de site installés (c'est-à-dire que vos paramètres les incluent) :
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
... alors vous aurez le request
disponible dans les modèles, et il contiendra une référence à l'objet courant Site
pour la demande en tant que request.site
. Vous pouvez ensuite récupérer le domaine dans un modèle avec :
{{request.site.domain}}
et le nom du site avec :
{{request.site.name}}