ฉันจะรับชื่อโดเมนของไซต์ปัจจุบันของฉันจากภายในแม่แบบ Django ได้อย่างไร ฉันลองค้นหาในแท็กและตัวกรองแล้ว แต่ไม่มีอะไรอยู่
ฉันจะรับชื่อโดเมนของไซต์ปัจจุบันของฉันจากภายในแม่แบบ Django ได้อย่างไร ฉันลองค้นหาในแท็กและตัวกรองแล้ว แต่ไม่มีอะไรอยู่
คำตอบ:
ฉันคิดว่าสิ่งที่คุณต้องการคือการเข้าถึงบริบทคำขอดูที่ RequestContext
Host:
ส่วนหัวและได้รับการตอบกลับด้วยโดเมนปลอมบางแห่งในหน้านั้นจะสร้างช่องโหว่ความปลอดภัยได้อย่างไร ฉันไม่เห็นความแตกต่างจากผู้ใช้ที่ใช้ HTML ที่สร้างขึ้นและแก้ไขตัวเองก่อนส่งไปยังเบราว์เซอร์ของเขาเอง
หากคุณต้องการส่วนหัวโฮสต์ HTTP จริงโปรดดูความคิดเห็นของ Daniel Roseman บนคำตอบของ @ Phsiao อีกทางเลือกหนึ่งคือถ้าคุณใช้เฟรมเวิร์ก contrib.sitesคุณสามารถตั้งชื่อโดเมนแบบบัญญัติสำหรับเว็บไซต์ในฐานข้อมูล (จับคู่โดเมนคำขอกับไฟล์การตั้งค่าด้วย SITE_ID ที่เหมาะสมเป็นสิ่งที่คุณต้องทำด้วยตัวเองผ่านทาง การตั้งค่าเว็บเซิร์ฟเวอร์) ในกรณีที่คุณกำลังมองหา:
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
current_site.domain
คุณต้องใส่วัตถุ current_site ลงในบริบทเทมเพลตด้วยตนเองหากคุณต้องการใช้ หากคุณกำลังใช้งานอยู่ทุกที่คุณสามารถจัดทำแพ็กเกจนั้นในตัวประมวลผลบริบทเทมเพลต
SITE_ID
การตั้งค่าของคุณเท่ากับid
คุณลักษณะของไซต์ปัจจุบันในแอป Sites (คุณสามารถค้นหาได้id
ในแผงผู้ดูแลระบบของไซต์) เมื่อคุณเรียกget_current
ใช้ Django จะนำของคุณSITE_ID
และส่งคืนSite
วัตถุที่มี id นั้นจากฐานข้อมูล
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 }}
วิธีการ
HTTP_X_FORWARDED_HOST
ส่วนหัว HTTP
request.build_absolute_uri
( docs.djangoproject.com/en/dev/ref/request-response/ ...... )
การเสริม Carl Meyer คุณสามารถสร้างตัวประมวลผลบริบทดังนี้:
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",
....
)
คุณสามารถเขียนรูตินของคุณเองหากต้องการจัดการโดเมนย่อยหรือ SSL ในตัวประมวลผลบริบท
รูปแบบของตัวประมวลผลบริบทที่ฉันใช้คือ:
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
เสื้อคลุมทำให้แน่ใจว่าสาย DB จะเกิดขึ้นเมื่อแม่แบบจริงใช้site
วัตถุ สิ่งนี้จะลบแบบสอบถามออกจากหน้าผู้ดูแลระบบ นอกจากนี้ยังแคชผลลัพธ์
และรวมไว้ในการตั้งค่า:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"module.context_processors.site",
....
)
ในเทมเพลตคุณสามารถใช้{{ site.domain }}
เพื่อรับชื่อโดเมนปัจจุบัน
แก้ไข:เพื่อรองรับการสลับโปรโตคอลด้วยให้ใช้:
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
ที่นี่เพราะแลมบ์ดาจะไม่ถูกเรียกถ้าไม่มีการเข้าถึง 'ไซต์' อยู่ดี
SimpleLazyObject
แต่ละอันRequestContext
จะเรียกใช้get_current_site()
และดำเนินการแบบสอบถาม SQL wrapper ทำให้แน่ใจว่าตัวแปรจะถูกประเมินเฉพาะเมื่อมันถูกใช้จริงในเทมเพลต
SimpleLazyObject
จะมีการประเมินหลีกเลี่ยงการทำงานที่ไม่จำเป็นจริงๆตั้งแต่Site
วัตถุแคช
from django.contrib.sites.shortcuts import get_current_site
ฉันรู้ว่าคำถามนี้เก่า แต่ฉันสะดุดเมื่อมองหาวิธี pythonic เพื่อรับโดเมนปัจจุบัน
def myview(request):
domain = request.build_absolute_uri('/')[:-1]
# that will build the complete domain: http://foobar.com
รวดเร็วและเรียบง่าย แต่ไม่ดีสำหรับการผลิต:
(ในมุมมอง)
request.scheme # http or https
request.META['HTTP_HOST'] # example.com
request.path # /some/content/1/
(ในเทมเพลต)
{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}
ตรวจสอบให้แน่ใจว่าใช้RequestContextซึ่งเป็นกรณีนี้หากคุณใช้การแสดงผลการแสดงผล
อย่าเชื่อถือrequest.META['HTTP_HOST']
ในการผลิต: ข้อมูลนั้นมาจากเบราว์เซอร์ ใช้คำตอบของ @ CarlMeyer แทน
request.scheme
แต่ผมได้รับข้อผิดพลาดเมื่อพยายามที่จะใช้ อาจมีเฉพาะใน django เวอร์ชันใหม่กว่าเท่านั้น
request.scheme
ถูกเพิ่มใน Django 1.7
{{ request.get_host }}
ควรป้องกันการโจมตีส่วนหัวของโฮสต์ HTTP เมื่อใช้ร่วมกับการALLOWED_HOSTS
ตั้งค่า (เพิ่มใน Django 1.4.4)
โปรดทราบว่า{{ request.META.HTTP_HOST }}
ไม่มีการป้องกันเดียวกัน ดูเอกสาร :
ALLOWED_HOSTS
รายการสตริงที่แสดงถึงชื่อโฮสต์ / โดเมนที่ไซต์ Django นี้สามารถให้บริการได้ นี่เป็นมาตรการรักษาความปลอดภัยเพื่อป้องกันการโจมตีส่วนหัวของโฮสต์ HTTPซึ่งเป็นไปได้แม้จะอยู่ภายใต้การกำหนดค่าเว็บเซิร์ฟเวอร์ที่ปลอดภัย
... ถ้า
Host
ส่วนหัว (หรือX-Forwarded-Host
ถ้าUSE_X_FORWARDED_HOST
เปิดใช้งาน) ไม่ตรงกับค่าใด ๆ ในรายการนี้วิธีการจะเพิ่มdjango.http.HttpRequest.get_host()
SuspiciousOperation
... การตรวจสอบนี้ใช้ผ่านทาง
get_host()
; หากรหัสของคุณเข้าถึงส่วนหัวของโฮสต์โดยตรงจากrequest.META
คุณกำลังข้ามการป้องกันความปลอดภัยนี้
สำหรับการใช้request
ในเทมเพลตของคุณการเรียกฟังก์ชั่นการแสดงผลเทมเพลตนั้นมีการเปลี่ยนแปลงใน Django 1.8ดังนั้นคุณจึงไม่ต้องจัดการอีกต่อไปRequestContext
โดยตรง
นี่คือวิธีการแสดงเทมเพลตสำหรับมุมมองโดยใช้ฟังก์ชันทางลัดrender()
:
from django.shortcuts import render
def my_view(request):
...
return render(request, 'my_template.html', context)
ต่อไปนี้เป็นวิธีสร้างเทมเพลตสำหรับอีเมลซึ่ง IMO เป็นกรณีทั่วไปที่คุณต้องการมูลค่าโฮสต์:
from django.template.loader import render_to_string
def my_view(request):
...
email_body = render_to_string(
'my_template.txt', context, request=request)
นี่คือตัวอย่างของการเพิ่ม URL แบบเต็มในเทมเพลตอีเมล request.schemeควรได้รับhttp
หรือhttps
ขึ้นอยู่กับสิ่งที่คุณใช้:
Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}
ฉันใช้เทมเพลตแท็กที่กำหนดเอง เพิ่มไปยังเช่น<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
ใช้ในเทมเพลตเช่นนี้:
{% load site %}
{% current_domain %}
get_current
เป็นวิธีการบันทึกไว้: docs.djangoproject.com/en/dev/ref/contrib/sites/…
'http://%s'
อาจเป็นปัญหาในกรณีที่มีการhttps
เชื่อมต่อ; แบบแผนไม่ได้เป็นแบบไดนามิกในกรณีนี้
คล้ายกับคำตอบของผู้ใช้ panchicore นี่คือสิ่งที่ฉันทำในเว็บไซต์ที่ง่ายมาก มันมีตัวแปรน้อยและทำให้พวกเขามีอยู่บนแม่แบบ
SITE_URL
จะถือเป็นค่าที่เหมือนexample.com
SITE_PROTOCOL
จะถือเป็นค่าที่เหมือนhttp
หรือhttps
SITE_PROTOCOL_URL
จะถือเป็นค่าที่เหมือนhttp://example.com
หรือจะถือเป็นค่าเช่นhttps://example.com
SITE_PROTOCOL_RELATIVE_URL
//example.com
โมดูล / 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'
จากนั้นในแม่แบบของคุณใช้พวกเขาเป็น{{ SITE_URL }}
, {{ SITE_PROTOCOL }}
, {{ SITE_PROTOCOL_URL }}
และ{{ SITE_PROTOCOL_RELATIVE_URL }}
ในแม่แบบ Django ที่คุณสามารถทำได้:
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
django.template.context_processors.request
ยัง [นี้วิธีการช่วย] ( simpleisbetterthancomplex.com/tips/2016/07/20/... )
ถ้าคุณใช้"คำขอ" โปรเซสเซอร์บริบทและใช้กรอบเว็บไซต์ Djangoและมีตัวกลางเว็บไซต์ที่ติดตั้ง (เช่นการตั้งค่าของคุณรวมถึงเหล่านี้):
INSTALLED_APPS = [
...
"django.contrib.sites",
...
]
MIDDLEWARE = [
...
"django.contrib.sites.middleware.CurrentSiteMiddleware",
...
]
TEMPLATES = [
{
...
"OPTIONS": {
"context_processors": [
...
"django.template.context_processors.request",
...
]
}
}
]
... แล้วคุณจะมีrequest
วัตถุที่มีอยู่ในแม่แบบและก็จะมีการอ้างอิงถึงในปัจจุบันสำหรับการร้องขอเป็นSite
request.site
จากนั้นคุณสามารถดึงข้อมูลโดเมนในแม่แบบด้วย:
{{request.site.domain}}
แล้ววิธีนี้ล่ะ ได้ผลสำหรับฉัน นอกจากนี้ยังใช้ใน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
จะทำให้คุณมีhttps
รูปแบบ (ถือว่าปลอดภัย) ซึ่งจะไม่ทำงานหากคุณมี URL คงที่ (ใช้ได้เฉพาะhttp://127.0.0.1
ไม่ใช่https://127.0.0.1
) ดังนั้นจึงไม่เหมาะเมื่อยังอยู่ในการพัฒนา
from django.contrib.sites.models import Site
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
คุณสามารถใช้{{ protocol }}://{{ domain }}
ในแม่แบบของคุณเพื่อรับชื่อโดเมนของคุณ
request.META['HTTP_HOST']
ช่วยให้คุณโดเมน{{ request.META.HTTP_HOST }}
ในแม่มันจะ