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 là-bas.
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 là-bas.
Réponses:
Je pense que ce que vous voulez, c'est avoir accès au contexte de la demande, voir RequestContext.
Host:tête et obtient une réponse avec le domaine usurpé quelque part sur une page, comment cela crée-t-il une faille de sécurité? Je ne vois pas en quoi cela diffère d'un utilisateur prenant le HTML généré et se modifiant avant de le nourrir dans son propre navigateur.
Si vous voulez l'en-tête HTTP Host réel, consultez le commentaire de Daniel Roseman sur la réponse de @ Phsiao. L'autre alternative est que si vous utilisez le framework contrib.sites , vous pouvez définir un nom de domaine canonique pour un site dans la base de données (mapper le domaine de requête à un fichier de paramètres avec le SITE_ID approprié est quelque chose que vous devez faire vous-même via votre configuration du serveur Web). Dans ce cas, vous recherchez:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
vous devrez placer vous-même l'objet current_site dans un contexte de modèle si vous souhaitez l'utiliser. Si vous l'utilisez partout, vous pouvez l'empaqueter dans un processeur de contexte de modèle.
SITE_IDparamètre est égal à l' idattribut du site actuel dans l'application Sites (vous pouvez le trouver iddans le panneau d'administration de Sites). Lorsque vous appelez get_current, Django prend votre SITE_IDet renvoie l' Siteobjet avec cet identifiant de la base de données.
print("get_current_site: ", get_current_site(request)) print("absolute uri: ", request.build_absolute_uri()) print("HTTP_HOST: ", request.META['HTTP_HOST']) get_current_site: localhost:8001 absolute uri: http://localhost:8001/... HTTP_HOST: localhost:8001
J'ai découvert la {{ request.get_host }}méthode.
HTTP_X_FORWARDED_HOSTen-tête HTTP.
request.build_absolute_uri( docs.djangoproject.com/en/dev/ref/request-response/… )
En complément de Carl Meyer, vous pouvez créer un processeur de contexte comme celui-ci:
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 souhaitez gérer des sous-domaines ou SSL dans le processeur de contexte.
La variante du processeur de contexte que j'utilise est:
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)),
}
L' SimpleLazyObjectencapsuleur garantit que l'appel de base de données se produit uniquement lorsque le modèle utilise réellement l' siteobjet. Cela supprime la requête des pages d'administration. Il met également en cache le résultat.
et incluez-le 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 prendre en charge également 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)),
}
SimpleLazyObjectici, car le lambda ne sera pas appelé si rien n'accède de toute façon au «site».
SimpleLazyObject, chacun RequestContextappellera get_current_site()et exécutera donc une requête SQL. L'encapsuleur s'assure que la variable n'est évaluée que lorsqu'elle est réellement utilisée dans le modèle.
SimpleLazyObjectest là pour éviter la réévaluation de la fonction, ce qui n'est pas vraiment nécessaire puisque l' Siteobjet est mis en cache.
from django.contrib.sites.shortcuts import get_current_site
Je sais que cette question est ancienne, mais je suis tombée dessus à 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
build_absolute_uriest documenté ici .
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 }}
Assurez-vous d'utiliser un RequestContext , ce qui est le cas si vous utilisez render .
Ne faites pas confiance request.META['HTTP_HOST']à la production: ces informations proviennent du navigateur. Utilisez plutôt la réponse de @ CarlMeyer
request.scheme. Peut-être uniquement disponible dans les versions plus récentes de django.
request.schemeété ajouté dans Django 1.7.
{{ request.get_host }}doit protéger contre les attaques d'en-tête HTTP Host lorsqu'il est utilisé avec le ALLOWED_HOSTSparamètre (ajouté dans Django 1.4.4).
Notez que {{ request.META.HTTP_HOST }}n'a pas la même protection. Voir la documentation :
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é pour empêcher les attaques d'en-tête HTTP Host , qui sont possibles même dans de nombreuses configurations de serveur Web apparemment sûres.
... Si l'en-
Hosttête (ouX-Forwarded-Hosts'ilUSE_X_FORWARDED_HOSTest activé) ne correspond à aucune valeur de cette liste, ladjango.http.HttpRequest.get_host()méthode augmenteraSuspiciousOperation.... Cette validation s'applique uniquement via
get_host(); si votre code accède à l'en-tête Host directement à partir derequest.METAvous, vous contournez cette protection de sécurité.
En ce qui concerne l'utilisation de requestdans votre modèle, les appels de la fonction de rendu de modèle ont changé dans Django 1.8 , vous n'avez donc plus à gérer RequestContextdirectement.
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 e-mail, lequel IMO est le cas le plus courant où vous souhaitez la valeur d'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; request.scheme devrait obtenir httpou httpsselon 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 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 %}
get_currentest une méthode documentée: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'pourrait être un problème en cas de httpsconnexion; schéma n'est pas dynamique dans ce cas.
Semblable à la réponse de l'utilisateur panchicore, c'est 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_URLtiendrait une valeur comme example.com
SITE_PROTOCOLtiendrait une valeur comme http ou https
SITE_PROTOCOL_URLcontiendrait une valeur comme http://example.comou https://example.com
SITE_PROTOCOL_RELATIVE_URLtiendrait 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, les utiliser 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>
django.template.context_processors.requestaussi [ce guide a aidé] ( simpleisbetterthancomplex.com/tips/2016/07/20/… )
Si vous utilisez le processeur de contexte "request" , et que vous utilisez le framework de sites Django et que le middleware du site est installé (c'est-à-dire que vos paramètres les incluent):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... alors vous aurez l' requestobjet disponible dans des modèles, et il contiendra une référence au courant Sitepour la demande sous forme de request.site. Vous pouvez ensuite récupérer le domaine dans un modèle avec:
{{request.site.domain}}
Et cette approche? Travaille 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)
localhostvous donnera un httpsschéma (il est considéré comme sécurisé) qui ne fonctionnera pas si vous avez une URL statique (seule http://127.0.0.1est valide, non https://127.0.0.1). Ce n'est donc pas idéal quand il est encore en développement.
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
Vous pouvez utiliser {{ protocol }}://{{ domain }}dans vos modèles pour obtenir votre nom de domaine.
request.META['HTTP_HOST']vous donne le domaine. Dans un modèle, ce serait{{ request.META.HTTP_HOST }}.