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_ID
pengaturan Anda sama dengan id
atribut situs saat ini di aplikasi Situs (Anda dapat menemukan id
di panel admin Situs). Ketika Anda menelepon get_current
, Django mengambil SITE_ID
dan mengembalikan Site
objek 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_HOST
header 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 SimpleLazyObject
wrapper 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)),
}
SimpleLazyObject
sini, 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.
SimpleLazyObject
ada untuk menghindari reevaluasi fungsi, yang tidak benar-benar diperlukan karena Site
objek 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_uri
didokumentasikan 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.scheme
ditambahkan dalam Django 1.7.
{{ request.get_host }}
harus melindungi terhadap serangan header HTTP Host ketika digunakan bersama-sama dengan ALLOWED_HOSTS
pengaturan (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
Host
tajuk (atauX-Forwarded-Host
jikaUSE_X_FORWARDED_HOST
diaktifkan) 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.META
Anda melewati perlindungan keamanan ini.
Adapun untuk menggunakan request
dalam template Anda, panggilan fungsi rendering template telah berubah di Django 1.8 , sehingga Anda tidak perlu lagi menangani RequestContext
secara 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 http
atau https
bergantung 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_current
adalah metode yang terdokumentasi: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'
bisa menjadi masalah dalam hal https
koneksi; 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_URL
akan memegang nilai suka example.com
SITE_PROTOCOL
akan memegang nilai suka http
atau https
SITE_PROTOCOL_URL
akan memegang nilai suka http://example.com
atau https://example.com
SITE_PROTOCOL_RELATIVE_URL
akan 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.request
juga [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 request
objek yang tersedia di template, dan itu akan berisi referensi ke Site
permintaan 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)
localhost
akan membuat Anda https
skema (Itu dianggap aman) yang tidak akan berfungsi jika Anda punya url statis (hanya http://127.0.0.1
valid, 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 }}
.