206 votes

Comment puis-je obtenir le nom de domaine de mon site dans un modèle Django ?

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.

30voto

Edward Newell Points 926

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

26voto

vdboor Points 6259

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)),
    }

25voto

S. Kirby Points 1812

{{ 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 (ou X-Forwarded-Host si USE_X_FORWARDED_HOST est activé) ne correspond à aucune valeur de cette liste, l'option django.http.HttpRequest.get_host() soulèvera SuspiciousOperation .

... Cette validation ne s'applique que via get_host() ; si votre code accède à l'en-tête Host directement à partir de request.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 %}

10voto

Denis Golomazov Points 1211

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 %}

9voto

user85461 Points 1620

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}}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X