ฉันมีบางสิ่งใน settings.py ที่ฉันสามารถเข้าถึงได้จากเทมเพลต แต่ฉันไม่สามารถหาวิธีทำได้ ฉันลองแล้ว
{{CONSTANT_NAME}}
แต่ดูเหมือนจะไม่ทำงาน เป็นไปได้ไหม
ฉันมีบางสิ่งใน settings.py ที่ฉันสามารถเข้าถึงได้จากเทมเพลต แต่ฉันไม่สามารถหาวิธีทำได้ ฉันลองแล้ว
{{CONSTANT_NAME}}
แต่ดูเหมือนจะไม่ทำงาน เป็นไปได้ไหม
คำตอบ:
Django ให้การเข้าถึงค่าคงที่การตั้งค่าที่ใช้บ่อยบางอย่างกับแม่แบบเช่นsettings.MEDIA_URL
และการตั้งค่าภาษาบางอย่างหากคุณใช้ django ที่สร้างขึ้นในมุมมองทั่วไปหรือส่งผ่านอาร์กิวเมนต์คำหลักอินสแตนซ์บริบทในrender_to_response
ฟังก์ชันทางลัด นี่คือตัวอย่างของแต่ละกรณี:
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.generic.simple import direct_to_template
def my_generic_view(request, template='my_template.html'):
return direct_to_template(request, template)
def more_custom_view(request, template='my_template.html'):
return render_to_response(template, {}, context_instance=RequestContext(request))
มุมมองเหล่านี้จะมีการตั้งค่าที่ใช้บ่อยหลายอย่างเช่นsettings.MEDIA_URL
มีให้ในเทมเพลตเช่น{{ MEDIA_URL }}
และอื่น ๆ
หากคุณกำลังมองหาการเข้าถึงค่าคงที่อื่น ๆ ในการตั้งค่าให้คลายค่าคงที่ที่คุณต้องการและเพิ่มลงในพจนานุกรมบริบทที่คุณใช้ในฟังก์ชั่นมุมมองของคุณเช่น:
from django.conf import settings
from django.shortcuts import render_to_response
def my_view_function(request, template='my_template.html'):
context = {'favorite_color': settings.FAVORITE_COLOR}
return render_to_response(template, context)
ตอนนี้คุณสามารถเข้าถึงแม่แบบของคุณเป็น settings.FAVORITE_COLOR
{{ favorite_color }}
django-settings-export
จะหลีกเลี่ยงความต้องการที่จะเขียนรหัสนี้ในทุกมุมมอง
หากเป็นค่าที่คุณต้องการสำหรับทุกคำขอ & แม่แบบการใช้ตัวประมวลผลบริบทจะเหมาะสมกว่า
นี่คือวิธี:
สร้างcontext_processors.py
ไฟล์ในไดเรกทอรีแอปของคุณ สมมติว่าฉันต้องการมีADMIN_PREFIX_VALUE
คุณค่าในทุกบริบท:
from django.conf import settings # import the settings file
def admin_media(request):
# return the value you want as a dictionnary. you may add multiple values in there.
return {'ADMIN_MEDIA_URL': settings.ADMIN_MEDIA_PREFIX}
เพิ่มตัวประมวลผลบริบทของคุณไปยังไฟล์settings.py :
TEMPLATES = [{
# whatever comes before
'OPTIONS': {
'context_processors': [
# whatever comes before
"your_app.context_processors.admin_media",
],
}
}]
ใช้RequestContext
ในมุมมองของคุณเพื่อเพิ่มตัวประมวลผลบริบทของคุณในแม่แบบของคุณ render
ทางลัดไม่นี้โดยอัตโนมัติ:
from django.shortcuts import render
def my_view(request):
return render(request, "index.html")
และในที่สุดในเทมเพลตของคุณ:
...
<a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a>
...
context_process.py
ถัดจากsettings.py
ไฟล์ของฉันและเพิ่มลง"context_processors.admin_media"
ในTEMPLATE_CONTEXT_PROCESSORS
รายการของฉัน นอกจากนี้คุณอาจต้องการเพิ่มบันทึกย่อในคำตอบของคุณเกี่ยวกับความจริงที่ว่าค่าเริ่มต้นของ TEMPLATE_CONTEXT_PROCESSORS ไม่ว่างเปล่าดังนั้นหากรหัสใด ๆ ที่มีอยู่ใช้ค่าใด ๆ ที่กำหนดโดยตัวประมวลผลบริบทเริ่มต้นเหล่านั้นจะไม่ทำงานจนกว่าคุณจะเพิ่มกลับ ในรายการอย่างชัดเจน
render
ทางลัดเพื่อหลีกเลี่ยงการรวม RequestContext อย่างชัดเจน: docs.djangoproject.com/en/1.6/topics/http/shortcuts/#render
ฉันพบวิธีที่ง่ายที่สุดในการเป็นแท็กเทมเพลตที่กำหนดเอง :
from django import template
from django.conf import settings
register = template.Library()
# settings value
@register.simple_tag
def settings_value(name):
return getattr(settings, name, "")
การใช้งาน:
{% settings_value "LANGUAGE_CODE" %}
{% settings_value "DATABASES" %}
ไม่เหมาะสม: กรณีใช้นี้ควรทำให้ชัดเจนว่าทำไมการตั้งค่าไม่พร้อมใช้งานในเทมเพลตเพื่อเริ่มต้น
templatetags
โฟลเดอร์ภายในแอปของคุณด้วย__init__.py
ไฟล์เปล่าและรหัสนี้เหมือนกับsettings.py
ในโฟลเดอร์นั้น 2) ในแม่แบบของคุณคุณเพิ่ม{% load settings %}
แล้วใช้แท็กใหม่ของคุณ!
ตรวจสอบdjango-settings-export
(ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียนโครงการนี้)
ตัวอย่างเช่น...
$ pip install django-settings-export
TEMPLATES = [
{
'OPTIONS': {
'context_processors': [
'django_settings_export.settings_export',
],
},
},
]
MY_CHEESE = 'Camembert';
SETTINGS_EXPORT = [
'MY_CHEESE',
]
<script>var MY_CHEESE = '{{ settings.MY_CHEESE }}';</script>
render
และไม่render_to_response
อีกวิธีในการทำเช่นนี้คือการสร้างแท็กแม่แบบที่กำหนดเองซึ่งสามารถให้คุณเก็บค่าจากการตั้งค่า
@register.tag
def value_from_settings(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, var = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0]
return ValueFromSettings(var)
class ValueFromSettings(template.Node):
def __init__(self, var):
self.arg = template.Variable(var)
def render(self, context):
return settings.__getattr__(str(self.arg))
จากนั้นคุณสามารถใช้:
{% value_from_settings "FQDN" %}
เพื่อพิมพ์บนหน้าใดก็ได้โดยไม่ต้องผ่านห่วงตัวประมวลผลบริบท
ฉันชอบวิธีแก้ปัญหาของ Berislav เพราะในเว็บไซต์ธรรมดา ๆ มันสะอาดและมีประสิทธิภาพ สิ่งที่ฉันไม่ชอบคือการเปิดเผยการตั้งค่าทั้งหมดยังคงจำใจ ดังนั้นสิ่งที่ฉันทำคือ:
from django import template
from django.conf import settings
register = template.Library()
ALLOWABLE_VALUES = ("CONSTANT_NAME_1", "CONSTANT_NAME_2",)
# settings value
@register.simple_tag
def settings_value(name):
if name in ALLOWABLE_VALUES:
return getattr(settings, name, '')
return ''
การใช้งาน:
{% settings_value "CONSTANT_NAME_1" %}
สิ่งนี้จะปกป้องค่าคงที่ใด ๆ ที่คุณไม่ได้ตั้งชื่อไม่ให้ใช้ในเทมเพลตและถ้าคุณต้องการที่จะได้รับแฟนซีคุณสามารถตั้งค่า tuple ในการตั้งค่าและสร้างแท็กเทมเพลตมากกว่าหนึ่งแท็กสำหรับหน้าแอพหรือพื้นที่ต่างๆ รวม tuple โลคัลกับ tuple การตั้งค่าตามต้องการจากนั้นทำรายการความเข้าใจเพื่อดูว่าค่านั้นยอมรับได้หรือไม่
ฉันเห็นด้วยบนเว็บไซต์ที่ซับซ้อนนี่เป็นเรื่องง่ายนิดหน่อย แต่มีค่าที่ดีที่จะมีอยู่ในแม่แบบสากลและดูเหมือนว่าจะทำงานได้ดี ขอบคุณ Berislav สำหรับแนวคิดดั้งเดิม!
if name in ALLOWABLE_VALUES: ...
'val' in ('val_first', 'second_val',)
จะFalse
ไม่มีปัญหา substring ที่นี่
if
แถลงการณ์ได้อย่างไร? ฉันต้องการตรวจสอบDEBUG
ค่า
ฉันปรับปรุงคำตอบของ chrisdew (เพื่อสร้างแท็กของคุณเอง) เล็กน้อย
ขั้นแรกสร้างไฟล์yourapp/templatetags/value_from_settings.py
ที่คุณกำหนดแท็กใหม่ของคุณเองvalue_from_settings
:
from django.template import TemplateSyntaxError, Variable, Node, Variable, Library
from yourapp import settings
register = Library()
# I found some tricks in URLNode and url from defaulttags.py:
# https://code.djangoproject.com/browser/django/trunk/django/template/defaulttags.py
@register.tag
def value_from_settings(parser, token):
bits = token.split_contents()
if len(bits) < 2:
raise TemplateSyntaxError("'%s' takes at least one " \
"argument (settings constant to retrieve)" % bits[0])
settingsvar = bits[1]
settingsvar = settingsvar[1:-1] if settingsvar[0] == '"' else settingsvar
asvar = None
bits = bits[2:]
if len(bits) >= 2 and bits[-2] == 'as':
asvar = bits[-1]
bits = bits[:-2]
if len(bits):
raise TemplateSyntaxError("'value_from_settings' didn't recognise " \
"the arguments '%s'" % ", ".join(bits))
return ValueFromSettings(settingsvar, asvar)
class ValueFromSettings(Node):
def __init__(self, settingsvar, asvar):
self.arg = Variable(settingsvar)
self.asvar = asvar
def render(self, context):
ret_val = getattr(settings,str(self.arg))
if self.asvar:
context[self.asvar] = ret_val
return ''
else:
return ret_val
คุณสามารถใช้แท็กนี้ในแม่แบบของคุณผ่าน:
{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" %}
หรือผ่าน
{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" as my_fqdn %}
ข้อดีของas ...
สัญกรณ์คือมันทำให้ง่ายต่อการใช้งานในblocktrans
บล็อกผ่านทาง{{my_fqdn}}
วิ
การเพิ่มคำตอบพร้อมคำแนะนำที่สมบูรณ์สำหรับการสร้างเทมเพลตแท็กแบบกำหนดเองที่แก้ปัญหานี้ด้วย Django 2.0+
ใน app โฟลเดอร์ของคุณสร้างโฟลเดอร์ที่เรียกว่าtemplatetags ในนั้นสร้าง__init__.pyและcustom_tags.py :
ในcustom_tags.pyสร้างฟังก์ชั่นแท็กที่กำหนดเองที่ให้การเข้าถึงกุญแจโดยพลการในการตั้งค่าคงที่:
from django import template
from django.conf import settings
register = template.Library()
@register.simple_tag
def get_setting(name):
return getattr(settings, name, "")
เพื่อทำความเข้าใจรหัสนี้ฉันแนะนำให้อ่านส่วนบนแท็กง่าย ๆใน Django docs
จากนั้นคุณต้องทำให้ Django รับรู้ถึงแท็กที่กำหนดเองนี้ (และเพิ่มเติม) โดยการโหลดไฟล์นี้ในเทมเพลตที่คุณจะใช้ เช่นเดียวกับที่คุณต้องโหลดแท็กแบบคงที่:
{% load custom_tags %}
เมื่อโหลดแล้วสามารถใช้งานได้เหมือนแท็กอื่น ๆ เพียงระบุการตั้งค่าเฉพาะที่คุณต้องการคืน ดังนั้นหากคุณมีตัวแปร BUILD_VERSION ในการตั้งค่าของคุณ:
{% get_setting "BUILD_VERSION" %}
โซลูชันนี้จะไม่ทำงานกับอาร์เรย์ แต่ถ้าคุณต้องการให้คุณใส่ตรรกะลงในแม่แบบของคุณ
หมายเหตุ: โซลูชันที่สะอาดและปลอดภัยยิ่งขึ้นอาจเป็นตัวประมวลผลบริบทที่กำหนดเองซึ่งคุณเพิ่มการตั้งค่าที่คุณต้องการให้กับบริบทที่มีให้กับเทมเพลตทั้งหมด วิธีนี้ช่วยลดความเสี่ยงในการแสดงผลการตั้งค่าที่ละเอียดอ่อนในแม่แบบโดยไม่ได้ตั้งใจ
เพิ่มรหัสนี้ไปยังไฟล์ชื่อcontext_processors.py
:
from django.conf import settings as django_settings
def settings(request):
return {
'settings': django_settings,
}
และแล้วในไฟล์ตั้งค่าของคุณรวมถึงเส้นทางเช่น'speedy.core.base.context_processors.settings'
(มีชื่อของคุณแอปและเส้นทาง) ในการตั้งค่าใน'context_processors'
TEMPLATES
(คุณสามารถดูตัวอย่างการตั้งค่า / base.pyและcontext_processors.py )
จากนั้นคุณสามารถใช้การตั้งค่าเฉพาะในรหัสแม่แบบใดก็ได้ ตัวอย่างเช่น:
{% if settings.SITE_ID == settings.SPEEDY_MATCH_SITE_ID %}
ปรับปรุง:SECRET_KEY
รหัสข้างตีแผ่การตั้งค่าทั้งหมดเพื่อแม่รวมทั้งข้อมูลที่สำคัญเช่นคุณ แฮกเกอร์อาจใช้คุณสมบัตินี้ในการแสดงข้อมูลดังกล่าวในเทมเพลต หากคุณต้องการแสดงเฉพาะการตั้งค่าเทมเพลตให้ใช้รหัสนี้แทน:
def settings(request):
settings_in_templates = {}
for attr in ["SITE_ID", ...]: # Write here the settings you want to expose to the templates.
if (hasattr(django_settings, attr)):
settings_in_templates[attr] = getattr(django_settings, attr)
return {
'settings': settings_in_templates,
}
SECRET_KEY
อันที่จริงการแก้ปัญหาของฉันหมายความว่าการตั้งค่าทั้งหมดเพื่อแม่รวมทั้งข้อมูลที่สำคัญเช่น แฮกเกอร์อาจใช้คุณสมบัตินี้ในทางที่ผิดเพื่อแสดงข้อมูลดังกล่าวในเทมเพลต
ตัวอย่างข้างต้นจาก bchhun นั้นดียกเว้นคุณต้องสร้างพจนานุกรมบริบทของคุณจาก settings.py อย่างชัดเจน ด้านล่างเป็นตัวอย่างที่ไม่ผ่านการทดสอบของวิธีที่คุณสามารถสร้างพจนานุกรมบริบทโดยอัตโนมัติจากแอตทริบิวต์ตัวพิมพ์ใหญ่ทั้งหมดของ settings.py (อีกครั้ง: "^ [A-Z0-9 _] + $")
ในตอนท้ายของ settings.py:
_context = {}
local_context = locals()
for (k,v) in local_context.items():
if re.search('^[A-Z0-9_]+$',k):
_context[k] = str(v)
def settings_context(context):
return _context
TEMPLATE_CONTEXT_PROCESSORS = (
...
'myproject.settings.settings_context',
...
)
หากมีคนพบคำถามนี้เหมือนฉันฉันจะโพสต์โซลูชันซึ่งใช้งานได้กับ Django 2.0:
แท็กนี้กำหนดค่า settings.py บางค่าให้กับตัวแปรของเทมเพลต:
การใช้งาน: {% get_settings_value template_var "SETTINGS_VAR" %}
from django import template
from django.conf import settings
register = template.Library()
class AssignNode(template.Node):
def __init__(self, name, value):
self.name = name
self.value = value
def render(self, context):
context[self.name] = getattr(settings, self.value.resolve(context, True), "")
return ''
@register.tag('get_settings_value')
def do_assign(parser, token):
bits = token.split_contents()
if len(bits) != 3:
raise template.TemplateSyntaxError("'%s' tag takes two arguments" % bits[0])
value = parser.compile_filter(bits[2])
return AssignNode(bits[1], value)
{% load my_custom_tags %}
# Set local template variable:
{% get_settings_value settings_debug "DEBUG" %}
# Output settings_debug variable:
{{ settings_debug }}
# Use variable in if statement:
{% if settings_debug %}
... do something ...
{% else %}
... do other stuff ...
{% endif %}
ดูเอกสารประกอบของ Django เกี่ยวกับวิธีสร้างแท็กเทมเพลตที่กำหนดเองได้ที่นี่: https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/
{% if settings_debug %}
{% if settings_debug == True %}
เป็นข้อเสนอแนะของคุณ{% if settings_debug %}
หากใช้มุมมองแบบคลาส:
#
# in settings.py
#
YOUR_CUSTOM_SETTING = 'some value'
#
# in views.py
#
from django.conf import settings #for getting settings vars
class YourView(DetailView): #assuming DetailView; whatever though
# ...
def get_context_data(self, **kwargs):
context = super(YourView, self).get_context_data(**kwargs)
context['YOUR_CUSTOM_SETTING'] = settings.YOUR_CUSTOM_SETTING
return context
#
# in your_template.html, reference the setting like any other context variable
#
{{ YOUR_CUSTOM_SETTING }}
ฉันพบสิ่งนี้เป็นวิธีที่ง่ายที่สุดสำหรับ Django 1.3:
views.py
from local_settings import BASE_URL
def root(request):
return render_to_response('hero.html', {'BASE_URL': BASE_URL})
hero.html
var BASE_URL = '{{ JS_BASE_URL }}';
ทั้ง IanSR และ bchhun แนะนำให้เอาชนะ TEMPLATE_CONTEXT_PROCESSORS ในการตั้งค่า โปรดทราบว่าการตั้งค่านี้มีค่าเริ่มต้นที่อาจทำให้เกิดสิ่งที่ไม่พึงประสงค์หากคุณแทนที่โดยไม่ต้องตั้งค่าเริ่มต้นใหม่ ค่าเริ่มต้นมีการเปลี่ยนแปลงใน Django เวอร์ชันล่าสุดด้วย
https://docs.djangoproject.com/en/1.3/ref/settings/#template-context-processors
TEMPLATE_CONTEXT_PROCESSORS เริ่มต้น:
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.contrib.messages.context_processors.messages")
หากเราต้องเปรียบเทียบบริบทกับแท็กเทมเพลตในตัวแปรเดียวการรู้ว่าตัวเลือกที่มีประสิทธิภาพมากขึ้นนั้นสามารถสร้างประโยชน์ได้ อย่างไรก็ตามคุณอาจจะดีกว่าที่จะจุ่มลงในการตั้งค่าเฉพาะจากแม่แบบที่ต้องการตัวแปรนั้น ในกรณีนั้นมันไม่มีเหตุผลที่จะส่งตัวแปรไปยังเทมเพลตทั้งหมด แต่ถ้าคุณกำลังส่งตัวแปรไปยังเทมเพลตทั่วไปเช่นเทมเพลต base.html แล้วมันก็ไม่สำคัญว่าเทมเพลต base.html นั้นจะถูกเรนเดอร์กับทุกคำขอหรือไม่ดังนั้นคุณสามารถใช้วิธีการใดก็ได้
หากคุณตัดสินใจที่จะใช้ตัวเลือกเทมเพลตแท็กให้ใช้รหัสต่อไปนี้เพื่อให้คุณสามารถส่งค่าเริ่มต้นในกรณีที่ตัวแปรในคำถามไม่ได้กำหนดไว้
ตัวอย่าง: get_from_settings my_variable เป็น my_context_value
ตัวอย่าง: get_from_settings my_variable my_default เป็น my_context_value
class SettingsAttrNode(Node):
def __init__(self, variable, default, as_value):
self.variable = getattr(settings, variable, default)
self.cxtname = as_value
def render(self, context):
context[self.cxtname] = self.variable
return ''
def get_from_setting(parser, token):
as_value = variable = default = ''
bits = token.contents.split()
if len(bits) == 4 and bits[2] == 'as':
variable = bits[1]
as_value = bits[3]
elif len(bits) == 5 and bits[3] == 'as':
variable = bits[1]
default = bits[2]
as_value = bits[4]
else:
raise TemplateSyntaxError, "usage: get_from_settings variable default as value " \
"OR: get_from_settings variable as value"
return SettingsAttrNode(variable=variable, default=default, as_value=as_value)
get_from_setting = register.tag(get_from_setting)