Làm cách nào để có được tên miền của trang web hiện tại của tôi từ trong mẫu Django? Tôi đã thử tìm kiếm trong thẻ và bộ lọc nhưng không có gì ở đó.
Làm cách nào để có được tên miền của trang web hiện tại của tôi từ trong mẫu Django? Tôi đã thử tìm kiếm trong thẻ và bộ lọc nhưng không có gì ở đó.
Câu trả lời:
Tôi nghĩ những gì bạn muốn là có quyền truy cập vào bối cảnh yêu cầu, xem RequestContext.
Host:
tiêu đề và nhận được phản hồi với tên miền giả mạo ở đâu đó trên một trang, làm thế nào điều đó tạo ra một lỗ hổng bảo mật? Tôi không thấy điều đó khác với người dùng lấy HTML được tạo và tự sửa đổi trước khi đưa nó vào trình duyệt của chính mình.
Nếu bạn muốn tiêu đề Máy chủ HTTP thực tế, hãy xem nhận xét của Daniel Roseman về câu trả lời của @ Phsiao. Cách khác là nếu bạn đang sử dụng khung contrib.sites , bạn có thể đặt tên miền chính cho Trang web trong cơ sở dữ liệu (ánh xạ miền yêu cầu thành tệp cài đặt với SITE_ID phù hợp là điều bạn phải tự thực hiện thông qua thiết lập máy chủ web). Trong trường hợp đó, bạn đang tìm kiếm:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
bạn phải tự đặt đối tượng current_site vào ngữ cảnh mẫu nếu bạn muốn sử dụng nó. Nếu bạn đang sử dụng nó ở mọi nơi, bạn có thể gói nó trong bộ xử lý bối cảnh mẫu.
SITE_ID
cài đặt của bạn có bằng id
thuộc tính của trang hiện tại trong ứng dụng Trang web không (bạn có thể tìm thấy id
trong bảng quản trị Trang web). Khi bạn gọi get_current
, Django lấy của bạn SITE_ID
và trả về Site
đối tượng có id đó từ cơ sở dữ liệu.
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
Tôi đã khám phá ra {{ request.get_host }}
phương pháp.
HTTP_X_FORWARDED_HOST
tiêu đề HTTP.
request.build_absolute_uri
( docs.djangoproject.com/en/dev/ref/request-response/ gợi ý )
Bổ sung cho Carl Meyer, bạn có thể tạo một bộ xử lý bối cảnh như thế này:
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",
....
)
bạn có thể viết rutine của riêng bạn nếu muốn xử lý tên miền phụ hoặc SSL trong bộ xử lý ngữ cảnh.
Biến thể của bộ xử lý bối cảnh tôi sử dụng là:
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)),
}
Trình SimpleLazyObject
bao bọc đảm bảo cuộc gọi DB chỉ xảy ra khi mẫu thực sự sử dụng site
đối tượng. Điều này loại bỏ truy vấn từ các trang quản trị. Nó cũng lưu trữ kết quả.
và bao gồm nó trong cài đặt:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
Trong mẫu, bạn có thể sử dụng {{ site.domain }}
để lấy tên miền hiện tại.
chỉnh sửa: để hỗ trợ chuyển đổi giao thức quá, sử dụng:
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
ở đây, vì lambda sẽ không được gọi nếu không có gì truy cập 'trang web'.
SimpleLazyObject
, mỗi cái RequestContext
sẽ gọi get_current_site()
và do đó thực hiện một truy vấn SQL. Trình bao bọc đảm bảo biến chỉ được đánh giá khi nó thực sự được sử dụng trong mẫu.
SimpleLazyObject
để tránh đánh giá lại chức năng, điều này không thực sự cần thiết vì Site
đối tượng được lưu trữ.
from django.contrib.sites.shortcuts import get_current_site
Tôi biết câu hỏi này đã cũ, nhưng tôi tình cờ tìm thấy một cách dễ hiểu để có được tên miền hiện tại.
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
build_absolute_uri
được ghi lại ở đây .
Nhanh chóng và đơn giản, nhưng không tốt cho sản xuất:
(trong một cái nhìn)
request.scheme # http or https
request.META['HTTP_HOST'] # example.com
request.path # /some/content/1/
(trong một mẫu)
{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
Hãy chắc chắn sử dụng RequestContext , đây là trường hợp nếu bạn đang sử dụng kết xuất .
Không tin tưởng request.META['HTTP_HOST']
vào sản xuất: thông tin đó đến từ trình duyệt. Thay vào đó, hãy sử dụng câu trả lời của @ CarlMeyer
request.scheme
. Có lẽ chỉ có sẵn trong các phiên bản mới hơn của django.
request.scheme
đã được thêm vào Django 1.7.
{{ request.get_host }}
phải bảo vệ chống lại các cuộc tấn công tiêu đề Máy chủ HTTP khi được sử dụng cùng với ALLOWED_HOSTS
cài đặt (được thêm vào trong Django 1.4.4).
Lưu ý rằng {{ request.META.HTTP_HOST }}
không có sự bảo vệ tương tự. Xem tài liệu :
ALLOWED_HOSTS
Danh sách các chuỗi đại diện cho tên máy chủ / tên miền mà trang Django này có thể phục vụ. Đây là một biện pháp bảo mật để ngăn chặn các cuộc tấn công tiêu đề Máy chủ HTTP , có thể xảy ra ngay cả dưới nhiều cấu hình máy chủ web có vẻ an toàn.
... Nếu
Host
tiêu đề (hoặcX-Forwarded-Host
nếuUSE_X_FORWARDED_HOST
được bật) không khớp với bất kỳ giá trị nào trong danh sách này,django.http.HttpRequest.get_host()
phương thức sẽ tăngSuspiciousOperation
.... Xác nhận này chỉ áp dụng thông qua
get_host()
; nếu mã của bạn truy cập vào tiêu đề Máy chủ trực tiếp từrequest.META
bạn thì bỏ qua bảo vệ bảo mật này.
Đối với việc sử dụng request
trong mẫu của bạn, các lệnh gọi chức năng kết xuất mẫu đã thay đổi trong Django 1.8 , do đó bạn không còn phải xử lý RequestContext
trực tiếp.
Dưới đây là cách hiển thị mẫu cho chế độ xem, sử dụng chức năng phím tắt render()
:
from django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
Đây là cách kết xuất mẫu cho email, IMO là trường hợp phổ biến hơn mà bạn muốn giá trị máy chủ:
from django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
Đây là một ví dụ về việc thêm một URL đầy đủ trong một mẫu email; request.scheme sẽ nhận được http
hoặc https
tùy thuộc vào những gì bạn đang sử dụng:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
Tôi sử dụng một thẻ mẫu tùy chỉnh. Thêm vào ví dụ <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
Sử dụng nó trong một mẫu như thế này:
{% load site %}
{% current_domain %}
get_current
là một phương pháp được ghi lại: docs.djangoproject.com/en/dev/ref/contrib/sites/ mẹo
'http://%s'
có thể là một vấn đề trong trường hợp https
kết nối; Đề án không năng động trong trường hợp này.
Tương tự như câu trả lời của người dùng panchicore, đây là những gì tôi đã làm trên một trang web rất đơn giản. Nó cung cấp một vài biến và làm cho chúng có sẵn trên mẫu.
SITE_URL
sẽ giữ một giá trị như example.com
SITE_PROTOCOL
sẽ giữ một giá trị như http
hoặc https
SITE_PROTOCOL_URL
sẽ giữ một giá trị như http://example.com
hoặc https://example.com
SITE_PROTOCOL_RELATIVE_URL
sẽ giữ một giá trị như thế nào //example.com
.
mô-đun / bối cảnh
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
}
cài đặt
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
SITE_URL = 'example.com'
Sau đó, trên các mẫu của bạn, sử dụng chúng như {{ SITE_URL }}
, {{ SITE_PROTOCOL }}
, {{ SITE_PROTOCOL_URL }}
và{{ SITE_PROTOCOL_RELATIVE_URL }}
Trong mẫu Django bạn có thể làm:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
django.template.context_processors.request
, cũng [how-to này giúp] ( simpleisbetterthancomplex.com/tips/2016/07/20/... )
Nếu bạn sử dụng bộ xử lý ngữ cảnh "yêu cầu" và đang sử dụng khung trang web Django và cài đặt phần mềm trung gian Trang web (tức là cài đặt của bạn bao gồm các cài đặt này):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... sau đó bạn sẽ có request
đối tượng có sẵn trong các mẫu và nó sẽ chứa một tham chiếu đến hiện tại Site
cho yêu cầu như request.site
. Sau đó, bạn có thể truy xuất tên miền trong một mẫu với:
{{request.site.domain}}
Phương pháp này thì sao? Làm việc cho tôi. Nó cũng được sử dụng trong đăng ký 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
sẽ giúp bạn có một https
lược đồ (Nó được coi là an toàn) sẽ không hoạt động nếu bạn có url tĩnh (chỉ http://127.0.0.1
hợp lệ, không phải https://127.0.0.1
). Vì vậy, nó không lý tưởng khi vẫn còn trong quá trình phát triển.
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
Bạn có thể sử dụng {{ protocol }}://{{ domain }}
trong các mẫu của bạn để có được tên miền của bạn.
request.META['HTTP_HOST']
cung cấp cho bạn tên miền. Trong một mẫu nó sẽ là{{ request.META.HTTP_HOST }}
.