Come posso ottenere il nome di dominio del mio sito attuale da un modello Django? Ho provato a cercare nel tag e nei filtri ma niente lì.
Come posso ottenere il nome di dominio del mio sito attuale da un modello Django? Ho provato a cercare nel tag e nei filtri ma niente lì.
Risposte:
Penso che ciò che vuoi sia avere accesso al contesto della richiesta, vedi RequestContext.
Host:
intestazione e riceve una risposta con il dominio contraffatto da qualche parte in una pagina, come può creare una falla nella sicurezza? Non vedo come questo differisca da un utente che prende l'HTML generato e si modifica prima di inviarlo al proprio browser.
Se vuoi l'header HTTP Host attuale, vedi il commento di Daniel Roseman sulla risposta di @ Phsiao. L'altra alternativa è che se stai usando il framework contrib.sites , puoi impostare un nome di dominio canonico per un sito nel database (mappare il dominio di richiesta su un file di impostazioni con il SITE_ID corretto è qualcosa che devi fare tu stesso tramite il tuo configurazione del server web). In quel caso stai cercando:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
dovresti mettere tu stesso l'oggetto current_site in un contesto template se vuoi usarlo. Se lo stai usando ovunque, puoi impacchettarlo in un processore di contesto modello.
SITE_ID
impostazioni siano uguali id
all'attributo del sito corrente nell'app Sites (puoi trovare il id
pannello di amministrazione di Sites). Quando chiami get_current
, Django prende il tuo SITE_ID
e restituisce l' Site
oggetto con quell'id dal database.
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
Ho scoperto il {{ request.get_host }}
metodo.
HTTP_X_FORWARDED_HOST
HTTP.
request.build_absolute_uri
( docs.djangoproject.com/en/dev/ref/request-response/… )
A completamento di Carl Meyer, puoi creare un processore di contesto come questo:
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",
....
)
puoi scrivere la tua routine se vuoi gestire sottodomini o SSL nel processore di contesto.
La variazione del processore di contesto che utilizzo è:
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)),
}
Il SimpleLazyObject
wrapper si assicura che la chiamata DB avvenga solo quando il modello utilizza effettivamente l' site
oggetto. Ciò rimuove la query dalle pagine di amministrazione. Inoltre memorizza nella cache il risultato.
e includilo nelle impostazioni:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
Nel modello, è possibile utilizzare {{ site.domain }}
per ottenere il nome di dominio corrente.
modifica: per supportare anche la commutazione del protocollo, utilizzare:
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)),
}
SimpleLazyObject
qui, perché lambda non verrà chiamato se nulla accede comunque al "sito".
SimpleLazyObject
, ognuno RequestContext
chiamerà get_current_site()
e quindi eseguirà una query SQL. Il wrapper si assicura che la variabile venga valutata solo quando viene effettivamente utilizzata nel modello.
SimpleLazyObject
è lì per evitare di rivalutazione della funzione, che non è realmente necessario in quanto l' Site
oggetto viene memorizzato nella cache.
from django.contrib.sites.shortcuts import get_current_site
So che questa domanda è vecchia, ma mi sono imbattuto in esso alla ricerca di un modo pitonico per ottenere il dominio corrente.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
build_absolute_uri
è documentato qui .
Veloce e semplice, ma non buono per la produzione:
(in una vista)
request.scheme # http or https
request.META['HTTP_HOST'] # example.com
request.path # /some/content/1/
(in un modello)
{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
Assicurati di usare un RequestContext , che è il caso se stai usando il rendering .
Non fidarti request.META['HTTP_HOST']
della produzione: queste informazioni provengono dal browser. Usa invece la risposta di @ CarlMeyer
request.scheme
. Forse disponibile solo nelle versioni più recenti di django.
request.scheme
stato aggiunto in Django 1.7.
{{ request.get_host }}
dovrebbe proteggere dagli attacchi di intestazione dell'host HTTP quando usato insieme ALLOWED_HOSTS
all'impostazione (aggiunto in Django 1.4.4).
Si noti che {{ request.META.HTTP_HOST }}
non ha la stessa protezione. Vedi i documenti :
allowed_hosts
Un elenco di stringhe che rappresentano i nomi host / dominio che questo sito Django può servire. Questa è una misura di sicurezza per prevenire attacchi di intestazione host HTTP , che sono possibili anche in molte configurazioni di server Web apparentemente sicure.
... Se l'
Host
intestazione (oX-Forwarded-Host
seUSE_X_FORWARDED_HOST
è abilitata) non corrisponde a nessun valore in questo elenco, ildjango.http.HttpRequest.get_host()
metodo aumenteràSuspiciousOperation
.... Questa convalida si applica solo tramite
get_host()
; se il tuo codice accede all'intestazione Host direttamente darequest.META
te, stai evitando questa protezione di sicurezza.
Per quanto riguarda l'utilizzo del request
modello, le chiamate alla funzione di rendering del modello sono cambiate in Django 1.8 , quindi non è più necessario gestirle RequestContext
direttamente.
Ecco come eseguire il rendering di un modello per una vista, utilizzando la funzione di scelta rapida render()
:
from django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
Ecco come eseguire il rendering di un modello per un'email, quale IMO è il caso più comune in cui si desidera il valore host:
from django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
Ecco un esempio di aggiunta di un URL completo in un modello di posta elettronica; request.scheme dovrebbe ottenere http
o in https
base a cosa stai usando:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
Uso un tag modello personalizzato. Aggiungi ad esempio <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
Usalo in un modello come questo:
{% load site %}
{% current_domain %}
get_current
è un metodo documentato: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'
potrebbe essere un problema in caso di https
connessione; lo schema non è dinamico in questo caso.
Simile alla risposta dell'utente Panchicore, questo è quello che ho fatto su un sito Web molto semplice. Fornisce alcune variabili e le rende disponibili nel modello.
SITE_URL
conterrebbe un valore come example.com
SITE_PROTOCOL
conterrebbe un valore come http
o https
SITE_PROTOCOL_URL
conterrebbe un valore come http://example.com
o https://example.com
SITE_PROTOCOL_RELATIVE_URL
conterrebbe un valore come //example.com
.
Modulo / 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'
Poi, i modelli, li usano come {{ SITE_URL }}
, {{ SITE_PROTOCOL }}
, {{ SITE_PROTOCOL_URL }}
e{{ SITE_PROTOCOL_RELATIVE_URL }}
In un modello Django puoi fare:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
django.template.context_processors.request
anche [questo how-to aiutato] ( simpleisbetterthancomplex.com/tips/2016/07/20/… )
Se si utilizza il processore di contesto "richiesta" e si utilizza il framework dei siti Django e si dispone del middleware del sito installato (ovvero le impostazioni includono queste):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... quindi avrai l' request
oggetto disponibile nei template e conterrà un riferimento alla corrente Site
per la richiesta come request.site
. È quindi possibile recuperare il dominio in un modello con:
{{request.site.domain}}
Che dire di questo approccio? Per me va bene. Viene anche usato nella registrazione django .
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)
localhost
darà uno https
schema (è considerato sicuro) che non funzionerà se hai l'URL statico (solo http://127.0.0.1
è valido, non https://127.0.0.1
). Quindi non è l'ideale quando è ancora in fase di sviluppo.
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
È possibile utilizzare {{ protocol }}://{{ domain }}
nei modelli per ottenere il nome del dominio.
request.META['HTTP_HOST']
ti dà il dominio. In un modello sarebbe{{ request.META.HTTP_HOST }}
.