Bagaimana cara mendapatkan nama domain dari situs saya saat ini dari dalam template Django? Saya sudah mencoba mencari di tag dan filter tetapi tidak ada.
Bagaimana cara mendapatkan nama domain dari situs saya saat ini dari dalam template Django? Saya sudah mencoba mencari di tag dan filter tetapi tidak ada.
Jawaban:
Saya pikir yang Anda inginkan adalah memiliki akses ke konteks permintaan, lihat RequestContext.
Host:header dan mendapat respons kembali dengan domain palsu di suatu tempat di halaman, bagaimana cara membuat lubang keamanan? Saya tidak melihat bagaimana itu berbeda dari pengguna yang mengambil HTML yang dihasilkan dan memodifikasi dirinya sendiri sebelum mengumpankannya ke browser miliknya.
Jika Anda ingin tajuk Host HTTP asli, lihat komentar Daniel Roseman pada jawaban @ Phsiao. Alternatif lain adalah jika Anda menggunakan kerangka contrib.sites , Anda dapat menetapkan nama domain kanonik untuk suatu Situs dalam basis data (memetakan domain permintaan ke file pengaturan dengan SITE_ID yang tepat adalah sesuatu yang harus Anda lakukan sendiri melalui Anda pengaturan server web). Dalam hal ini yang Anda cari:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
Anda harus menempatkan sendiri objek current_site ke dalam konteks template jika Anda ingin menggunakannya. Jika Anda menggunakannya di mana-mana, Anda bisa mengemasnya dalam prosesor konteks templat.
SITE_IDpengaturan Anda sama dengan idatribut situs saat ini di aplikasi Situs (Anda dapat menemukan iddi panel admin Situs). Ketika Anda menelepon get_current, Django mengambil SITE_IDdan mengembalikan Siteobjek dengan id itu dari 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
Saya telah menemukan {{ request.get_host }}metodenya.
HTTP_X_FORWARDED_HOSTheader HTTP.
request.build_absolute_uri( docs.djangoproject.com/en/dev/ref/request-response/… )
Melengkapi Carl Meyer, Anda dapat membuat pemroses konteks seperti ini:
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",
....
)
Anda dapat menulis rutine Anda sendiri jika ingin menangani subdomain atau SSL di pemroses konteks.
Variasi dari pengolah konteks yang saya gunakan adalah:
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)),
}
The SimpleLazyObjectwrapper memastikan panggilan DB hanya terjadi ketika template benar-benar menggunakansite objek. Ini menghapus kueri dari halaman admin. Itu juga cache hasilnya.
dan sertakan dalam pengaturan:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
Di dalam templat, Anda bisa menggunakan {{ site.domain }} untuk mendapatkan nama domain saat ini.
sunting: untuk mendukung pengalihan protokol juga, gunakan:
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)),
}
SimpleLazyObjectsini, karena lambda tidak akan dipanggil jika tidak ada yang mengakses 'situs'.
SimpleLazyObject, masing RequestContext- masing akan memanggil get_current_site(), dan karenanya menjalankan query SQL. Wrapper memastikan variabel hanya dievaluasi ketika sebenarnya digunakan dalam template.
SimpleLazyObjectada untuk menghindari reevaluasi fungsi, yang tidak benar-benar diperlukan karena Siteobjek cache.
from django.contrib.sites.shortcuts import get_current_site
Saya tahu pertanyaan ini sudah lama, tetapi saya menemukan itu mencari cara pythonic untuk mendapatkan domain saat ini.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
build_absolute_urididokumentasikan di sini .
Cepat dan sederhana, tetapi tidak baik untuk produksi:
(dalam tampilan)
request.scheme # http or https
request.META['HTTP_HOST'] # example.com
request.path # /some/content/1/
(dalam templat)
{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
Pastikan untuk menggunakan RequestContext , yang merupakan kasus jika Anda menggunakan render .
Jangan percaya request.META['HTTP_HOST']pada produksi: info itu berasal dari browser. Sebagai gantinya, gunakan jawaban @ CarlMeyer
request.scheme. Mungkin hanya tersedia di Django versi terbaru.
request.schemeditambahkan dalam Django 1.7.
{{ request.get_host }}harus melindungi terhadap serangan header HTTP Host ketika digunakan bersama-sama dengan ALLOWED_HOSTSpengaturan (ditambahkan dalam Django 1.4.4).
Perhatikan bahwa {{ request.META.HTTP_HOST }}tidak memiliki perlindungan yang sama. Lihat dokumen :
ALLOWED_HOSTS
Daftar string yang mewakili nama host / domain yang dapat dilayani oleh situs Django ini. Ini adalah langkah keamanan untuk mencegah serangan header HTTP Host , yang dimungkinkan bahkan di bawah banyak konfigurasi server web yang tampaknya aman.
... Jika
Hosttajuk (atauX-Forwarded-HostjikaUSE_X_FORWARDED_HOSTdiaktifkan) tidak cocok dengan nilai apa pun dalam daftar ini,django.http.HttpRequest.get_host()metode akan naikSuspiciousOperation.... Validasi ini hanya berlaku melalui
get_host(); jika kode Anda mengakses header Host langsung darirequest.METAAnda melewati perlindungan keamanan ini.
Adapun untuk menggunakan requestdalam template Anda, panggilan fungsi rendering template telah berubah di Django 1.8 , sehingga Anda tidak perlu lagi menangani RequestContextsecara langsung.
Berikut cara merender templat untuk tampilan, menggunakan fungsi pintasan render():
from django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
Berikut cara merender templat untuk email, IMO mana yang merupakan kasus paling umum di mana Anda menginginkan nilai host:
from django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
Berikut ini contoh menambahkan URL lengkap dalam templat email; request.scheme harus mendapatkan httpatau httpsbergantung pada apa yang Anda gunakan:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
Saya menggunakan tag templat khusus. Tambahkan ke misalnya <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
Gunakan dalam template seperti ini:
{% load site %}
{% current_domain %}
get_currentadalah metode yang terdokumentasi: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'bisa menjadi masalah dalam hal httpskoneksi; Skema tidak dinamis dalam hal ini.
Mirip dengan balasan pengguna panchicore, ini adalah apa yang saya lakukan di situs web yang sangat sederhana. Ini memberikan beberapa variabel dan membuatnya tersedia di templat.
SITE_URLakan memegang nilai suka example.com
SITE_PROTOCOLakan memegang nilai suka http atau https
SITE_PROTOCOL_URLakan memegang nilai suka http://example.comatau https://example.com
SITE_PROTOCOL_RELATIVE_URLakan memegang nilai suka//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'
Kemudian, pada template Anda, menggunakannya sebagai {{ SITE_URL }}, {{ SITE_PROTOCOL }}, {{ SITE_PROTOCOL_URL }}dan{{ SITE_PROTOCOL_RELATIVE_URL }}
Dalam template Django yang dapat Anda lakukan:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
django.template.context_processors.requestjuga [ini bagaimana-untuk membantu] ( simpleisbetterthancomplex.com/tips/2016/07/20/ ... )
Jika Anda menggunakan pemroses konteks "permintaan" , dan sedang menggunakan kerangka kerja situs Django , dan instal middleware Situs (mis. Pengaturan Anda mencakup ini):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... maka Anda akan memiliki requestobjek yang tersedia di template, dan itu akan berisi referensi ke Sitepermintaan saat ini sebagai request.site. Anda kemudian dapat mengambil domain dalam templat dengan:
{{request.site.domain}}
Bagaimana dengan pendekatan ini? Bekerja untukku. Ini juga digunakan dalam pendaftaran 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)
localhostakan membuat Anda httpsskema (Itu dianggap aman) yang tidak akan berfungsi jika Anda punya url statis (hanya http://127.0.0.1valid, tidak https://127.0.0.1). Jadi tidak ideal saat masih dalam pengembangan.
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
Anda dapat menggunakan {{ protocol }}://{{ domain }}template Anda untuk mendapatkan nama domain Anda.
request.META['HTTP_HOST']memberi Anda domain. Dalam sebuah templat akan seperti itu{{ request.META.HTTP_HOST }}.