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_IDayarınızın idSites uygulamasındaki mevcut sitenin özelliğine eşit olup olmadığını kontrol edin ( idSiteler yönetici panelinde bulabilirsiniz ). Aradığınızda get_current, Django nesnenizi alır SITE_IDve Sitebu 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_HOSTHTTP ü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)),
}
SimpleLazyObjectSarıcı şablonu aslında kullandığında DB arama yalnızca olmuyor emin olur sitenesneyi. 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)),
}
SimpleLazyObjectBurada 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 Sitenesne ö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_uriburada 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_HOSTSayarla 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-HosteğerUSE_X_FORWARDED_HOSTbu 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.METAsizden 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 RequestContextdoğ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 httpveya httpskullandığı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_currentbelgelenmiş bir yöntemdir: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'httpsbağ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_URLgibi bir değer yapacağını example.com
SITE_PROTOCOLgibi bir değeri yapacağını http veya https
SITE_PROTOCOL_URLbenzeri bir değeri yapacağını http://example.comveya https://example.com
SITE_PROTOCOL_RELATIVE_URLbenzeri 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.requestda [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 requestnesnenin şablonlarda kullanılabilir Siteolması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)
localhostbir httpsşema (Güvenli olarak kabul edilir) alacaktır (sadece http://127.0.0.1geç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 }}.