web-dev-qa-db-fra.com

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

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.

130
mog

Je pense que ce que vous voulez, c'est avoir accès au contexte de la requête, voir RequestContext.

56
phsiao

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.

88
Carl Meyer

J'ai découvert la méthode {{ request.get_Host }} .

66
danbruegge

En complément de Carl Meyer, vous pouvez créer un processeur de contexte comme ceci:

module.context_processors.py

from Django.conf import settings

def site(request):
    return {'SITE_URL': settings.SITE_URL}

paramètres.py locaux

SITE_URL = 'http://google.com' # this will reduce the Sites framework db call.

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )

modèles renvoyant l'instance de contexte du site url est {{SITE_URL}}

vous pouvez écrire votre propre rutine si vous voulez gérer des sous-domaines ou SSL dans le processeur de contexte.

53
panchicore

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

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
16
misterte

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

12
Edward Newell

{{ 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 (ou X-Forwarded-Host si USE_X_FORWARDED_Host est activé) ne correspond à aucune valeur de cette liste, la méthode Django.http.HttpRequest.get_Host() lèvera SuspiciousOperation.

... Cette validation ne s'applique que via get_Host(); Si votre code accède à l'en-tête de l'hôte directement à partir de request.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 %}
10
S. Kirby

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 %}
8
Dennis Golomazov

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

2
Julián Landerreche

Dans un modèle Django, vous pouvez faire:

<a href="{{ request.scheme }}://{{ request.META.HTTP_Host }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
0
Dos
from Django.contrib.sites.models import Site
if Site._meta.installed:
    site = Site.objects.get_current()
else:
    site = RequestSite(request)
0
Muneeb Ahmad

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)
0
user9434062