Mevcut sitemin alan adını bir Django şablonundan nasıl alabilirim? Etikete ve filtrelere bakmayı denedim ama hiçbir şey yok.
Mevcut sitemin alan adını bir Django şablonundan nasıl alabilirim? Etikete ve filtrelere bakmayı denedim ama hiçbir şey yok.
Yanıtlar:
İstediğiniz şey, istek bağlamına erişim sağlamak olduğunu düşünüyorum, bkz. RequestContext.
Host:
üstbilgi sahtekarlığı yapar ve sahtekarlık alan adıyla sayfanın herhangi bir yerinde yanıt alırsa, bu nasıl güvenlik açığı oluşturur? Bunun, oluşturulan HTML'yi alan ve kendi tarayıcısına beslemeden önce kendini değiştiren bir kullanıcıdan nasıl farklı olduğunu görmüyorum.
Gerçek HTTP Ana Bilgisayar başlığını istiyorsanız, Daniel Roseman'ın @ Phsiao'nun cevabı hakkındaki yorumuna bakın. Diğer bir alternatif, katkı.sites çerçevesini kullanıyorsanız, veritabanındaki bir Site için kanonik bir alan adı ayarlayabilirsiniz (istek alanını uygun SITE_ID değerine sahip bir ayar dosyasıyla eşleştirmek, web sunucusu kurulumu). Bu durumda:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
kullanmak istiyorsanız current_site nesnesini bir şablon bağlamına koymanız gerekir. Her yerde kullanıyorsanız, bunu bir şablon bağlamı işlemcisinde paketleyebilirsiniz.
SITE_ID
ayarınızın id
Sites uygulamasındaki mevcut sitenin özelliğine eşit olup olmadığını kontrol edin ( id
Siteler yönetici panelinde bulabilirsiniz ). Aradığınızda get_current
, Django nesnenizi alır SITE_ID
ve Site
bu kimliğe sahip nesneyi veritabanından döndürür .
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
{{ request.get_host }}
Yöntemi keşfettim .
HTTP_X_FORWARDED_HOST
HTTP üstbilgisini hesaba kattığı için ana bilgisayara bir HTTP proxy veya yük dengeleyici aracılığıyla ulaşıldığında kesinlikle daha eksiksizdir .
request.build_absolute_uri
( docs.djangoproject.com/en/dev/ref/request-response/… )
Carl Meyer'ı tamamlayarak, aşağıdaki gibi bir bağlam işlemcisi yapabilirsiniz:
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",
....
)
bağlam işlemcisinde alt alan adlarını veya SSL'yi işlemek istiyorsanız kendi rutininizi yazabilirsiniz.
Kullandığım bağlam işlemcisinin varyasyonu:
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)),
}
SimpleLazyObject
Sarıcı şablonu aslında kullandığında DB arama yalnızca olmuyor emin olur site
nesneyi. Bu, sorguyu yönetici sayfalarından kaldırır. Ayrıca sonucu önbelleğe alır.
ve ayarlara ekleyin:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
Şablonda, {{ site.domain }}
geçerli alan adını almak için kullanabilirsiniz .
edit: protokol geçişini de desteklemek için şunu kullanın:
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
Burada kullanmanıza gerek yok, çünkü yine de hiçbir şey 'siteye' erişemezse lambda çağrılmaz.
SimpleLazyObject
, her biri RequestContext
çağırır get_current_site()
ve bu nedenle bir SQL sorgusu yürütür. Sarıcı, değişkenin yalnızca şablonda gerçekten kullanıldığında değerlendirilmesini sağlar.
SimpleLazyObject
Çünkü gerçekten gerekli değildir fonksiyonun yeniden değerlendirilmesini önlemek için orada Site
nesne önbelleğe alınır.
from django.contrib.sites.shortcuts import get_current_site
Bu sorunun eski olduğunu biliyorum, ama mevcut etki alanı elde etmek için pythonic bir yol arayan tökezledi.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
build_absolute_uri
burada belgelenmiştir .
Hızlı ve basit, ancak üretim için iyi değil:
(bir görünümde)
request.scheme # http or https
request.META['HTTP_HOST'] # example.com
request.path # /some/content/1/
(bir şablonda)
{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
Bir kullandığınızdan emin olun RequestContext kullandığınız takdirde böyledir, işlemek .
request.META['HTTP_HOST']
Üretime güvenmeyin : bu bilgi tarayıcıdan gelir. Bunun yerine, @ CarlMeyer'ın cevabını kullanın
request.scheme
. Belki de sadece django'nun yeni sürümlerinde mevcuttur.
request.scheme
, Django 1.7'ye eklendi.
{{ request.get_host }}
ALLOWED_HOSTS
ayarla birlikte kullanıldığında HTTP Ana Bilgisayar üstbilgi saldırılarına karşı koruma sağlamalıdır (Django 1.4.4'te eklenmiştir).
{{ request.META.HTTP_HOST }}
Aynı korumaya sahip olmadığını unutmayın . Belgelere bakın :
ALLOWED_HOSTS
Bu Django sitesinin sunabileceği ana bilgisayar / etki alanı adlarını temsil eden dizelerin listesi. Bu, görünüşte güvenli olan birçok web sunucusu yapılandırmasında bile mümkün olan HTTP Ana Bilgisayar üstbilgisi saldırılarını önlemek için bir güvenlik önlemidir .
... Eğer
Host
(veya başlığaX-Forwarded-Host
eğerUSE_X_FORWARDED_HOST
bu listedeki herhangi bir değer uymuyor etkindir),django.http.HttpRequest.get_host()
yöntem yükseltecektirSuspiciousOperation
.... Bu doğrulama sadece
get_host()
; kodunuz doğrudanrequest.META
sizden Host başlığına erişiyorsa bu güvenlik korumasını atlıyorsunuz demektir.
request
Şablonunuzda kullanılmaya gelince , Django 1.8'de şablon oluşturma işlevi çağrıları değişti , bu yüzden artık RequestContext
doğrudan işlemek zorunda değilsiniz .
Kısayol işlevini kullanarak bir görünüm için şablonun nasıl oluşturulacağı aşağıda açıklanmıştır render()
:
from django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
Bir e-posta için nasıl şablon oluşturulacağı aşağıda açıklanmaktadır: IMO, ana makine değerini istediğiniz daha yaygın bir durumdur:
from django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
Aşağıda, bir e-posta şablonuna tam URL ekleme örneği; request.scheme almalısınız http
veya https
kullandığınız hangi bağlı:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
Özel bir şablon etiketi kullanıyorum. Örneğin ekle <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
Şunun gibi bir şablonda kullanın:
{% load site %}
{% current_domain %}
get_current
belgelenmiş bir yöntemdir: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'
https
bağlantı durumunda bir sorun olabilir ; şema bu durumda dinamik değildir.
Kullanıcı panchicore'un cevabına benzer şekilde, bu çok basit bir web sitesinde yaptığım şey. Birkaç değişken sağlar ve bunları şablonda kullanılabilir hale getirir.
SITE_URL
gibi bir değer yapacağını example.com
SITE_PROTOCOL
gibi bir değeri yapacağını http
veya https
SITE_PROTOCOL_URL
benzeri bir değeri yapacağını http://example.com
veya https://example.com
SITE_PROTOCOL_RELATIVE_URL
benzeri bir değeri yapacağını //example.com
.
modül / 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'
Ardından, şablonlara olarak bunları kullanmak {{ SITE_URL }}
, {{ SITE_PROTOCOL }}
, {{ SITE_PROTOCOL_URL }}
ve{{ SITE_PROTOCOL_RELATIVE_URL }}
Bir Django şablonunda şunları yapabilirsiniz:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
django.template.context_processors.request
da [bu nasıl yardımcı oldu] isteğini etkinleştirmek zorunda kaldım ( simpleisbetterthancomplex.com/tips/2016/07/20/… )
Eğer kullanırsanız "istek" bağlam işlemci ve kullandığınız Django siteleri çerçeve ve sahip Sitesi katman yüklü (yani ayarlarınız bu ekleyin):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... sonra request
nesnenin şablonlarda kullanılabilir Site
olmasını sağlar ve istek için geçerli olana bir başvuru içerir request.site
. Ardından, aşağıdakileri içeren bir şablondaki etki alanını alabilirsiniz:
{{request.site.domain}}
Bu yaklaşım ne olacak? Benim için çalışıyor. Django kaydında da kullanılır .
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
bir https
şema (Güvenli olarak kabul edilir) alacaktır (sadece http://127.0.0.1
geçerlidir, değil https://127.0.0.1
). Bu yüzden hala geliştirme aşamasında değil.
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
{{ protocol }}://{{ domain }}
Alan adınızı almak için şablonlarınızda kullanabilirsiniz .
request.META['HTTP_HOST']
size alan adını verir. Bir şablonda olurdu{{ request.META.HTTP_HOST }}
.