Tôi có một số nội dung trong settings.txt mà tôi muốn có thể truy cập từ một mẫu, nhưng tôi không thể tìm ra cách để làm điều đó. Tôi đã thử
{{CONSTANT_NAME}}
nhưng điều đó dường như không hoạt động. Điều này có thể không?
Tôi có một số nội dung trong settings.txt mà tôi muốn có thể truy cập từ một mẫu, nhưng tôi không thể tìm ra cách để làm điều đó. Tôi đã thử
{{CONSTANT_NAME}}
nhưng điều đó dường như không hoạt động. Điều này có thể không?
Câu trả lời:
Django cung cấp quyền truy cập vào một số hằng số cài đặt được sử dụng thường xuyên cho mẫu như settings.MEDIA_URL
và một số cài đặt ngôn ngữ nếu bạn sử dụng chế độ xem chung của django hoặc truyền vào đối số từ khóa ngữ cảnh trong render_to_response
hàm phím tắt. Đây là một ví dụ về mỗi trường hợp:
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))
Các chế độ xem này sẽ có một số cài đặt được sử dụng thường xuyên như settings.MEDIA_URL
có sẵn cho mẫu như {{ MEDIA_URL }}
, v.v.
Nếu bạn đang tìm kiếm quyền truy cập vào các hằng số khác trong cài đặt, thì chỉ cần giải nén các hằng số bạn muốn và thêm chúng vào từ điển ngữ cảnh bạn đang sử dụng trong chức năng xem của mình, như vậy:
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)
Bây giờ bạn có thể truy cập settings.FAVORITE_COLOR
vào mẫu của bạn như {{ favorite_color }}
.
django-settings-export
để tránh sự cần thiết phải viết mã này trong mọi chế độ xem.
Nếu đó là giá trị bạn muốn có cho mọi yêu cầu & mẫu, sử dụng bộ xử lý ngữ cảnh sẽ phù hợp hơn.
Đây là cách thực hiện:
Tạo một context_processors.py
tập tin trong thư mục ứng dụng của bạn. Hãy nói rằng tôi muốn có ADMIN_PREFIX_VALUE
giá trị trong mọi bối cảnh:
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}
thêm bộ xử lý ngữ cảnh của bạn vào tệp settings.txt của bạn :
TEMPLATES = [{
# whatever comes before
'OPTIONS': {
'context_processors': [
# whatever comes before
"your_app.context_processors.admin_media",
],
}
}]
Sử dụng RequestContext
trong chế độ xem của bạn để thêm bộ xử lý ngữ cảnh trong mẫu của bạn. Các render
shortcut thực hiện điều này tự động:
from django.shortcuts import render
def my_view(request):
return render(request, "index.html")
và cuối cùng, trong mẫu của bạn:
...
<a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a>
...
context_process.py
ngay bên cạnh settings.py
tệp của mình và thêm vào danh sách "context_processors.admin_media"
của mình TEMPLATE_CONTEXT_PROCESSORS
. Ngoài ra, bạn có thể muốn thêm một ghi chú trong câu trả lời của mình về thực tế là giá trị mặc định của TEMPLATE_CONTEXT_PROCESSORS không trống, vì vậy, nếu bất kỳ mã hiện có nào sử dụng bất kỳ giá trị nào được đặt bởi các bộ xử lý bối cảnh mặc định đó, chúng sẽ không hoạt động trừ khi bạn thêm lại chúng vào danh sách một cách rõ ràng.
render
phím tắt để tránh phải bao gồm RequestContext: docs.djangoproject.com/en/1.6/topics/http/shortype/#render
Tôi thấy cách tiếp cận đơn giản nhất là một thẻ mẫu tùy chỉnh duy nhất :
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, "")
Sử dụng:
{% settings_value "LANGUAGE_CODE" %}
{% settings_value "DATABASES" %}
? Ca sử dụng này sẽ làm rõ lý do tại sao các cài đặt không có sẵn trong các mẫu để bắt đầu.
templatetags
thư mục bên trong ứng dụng của bạn với một __init__.py
tệp trống và mã này như settings.py
trong thư mục đó. 2) trong mẫu của bạn, bạn thêm {% load settings %}
và sau đó sử dụng thẻ mới của bạn!
Kiểm tra django-settings-export
(từ chối trách nhiệm: Tôi là tác giả của dự án này).
Ví dụ...
$ 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
và khôngrender_to_response
Một cách khác để làm điều này là tạo thẻ mẫu tùy chỉnh có thể cho phép bạn loại bỏ các giá trị trong cài đặt.
@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))
Sau đó bạn có thể sử dụng:
{% value_from_settings "FQDN" %}
để in nó trên bất kỳ trang nào, mà không cần nhảy qua các bộ xử lý ngữ cảnh.
Tôi thích giải pháp của Berislav, bởi vì trên các trang web đơn giản, nó sạch sẽ và hiệu quả. Điều tôi KHÔNG thích là phơi bày tất cả các hằng số cài đặt willy-nilly. Vì vậy, những gì tôi đã làm là:
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 ''
Sử dụng:
{% settings_value "CONSTANT_NAME_1" %}
Điều này bảo vệ mọi hằng số mà bạn chưa đặt tên sử dụng trong mẫu và nếu bạn muốn thực sự ưa thích, bạn có thể đặt một tuple trong cài đặt và tạo nhiều hơn một thẻ mẫu cho các trang, ứng dụng hoặc khu vực khác nhau và chỉ cần kết hợp một bộ dữ liệu cục bộ với bộ cài đặt khi cần, sau đó thực hiện việc hiểu danh sách để xem giá trị có được chấp nhận hay không.
Tôi đồng ý, trên một trang web phức tạp, điều này hơi đơn giản, nhưng có những giá trị sẽ rất hay khi có phổ biến trong các mẫu và điều này dường như hoạt động tốt. Cảm ơn Berislav cho ý tưởng ban đầu!
if name in ALLOWABLE_VALUES: ...
'val' in ('val_first', 'second_val',)
là False
, không có vấn đề chuỗi con ở đây.
if
tuyên bố? tôi muốn kiểm tra DEBUG
giá trị
Tôi đã cải thiện câu trả lời của chrisdew (để tạo thẻ của riêng bạn) một chút.
Đầu tiên, tạo tệp yourapp/templatetags/value_from_settings.py
mà bạn xác định thẻ mới của riêng mình 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
Bạn có thể sử dụng thẻ này trong Mẫu của bạn thông qua:
{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" %}
hoặc thông qua
{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" as my_fqdn %}
Ưu điểm của as ...
ký hiệu là điều này giúp dễ dàng sử dụng trong blocktrans
các khối thông qua một cách đơn giản {{my_fqdn}}
.
Thêm câu trả lời với hướng dẫn đầy đủ để tạo thẻ mẫu tùy chỉnh giải quyết vấn đề này, với Django 2.0+
Trong thư mục ứng dụng của bạn, hãy tạo một thư mục có tên templatetags . Trong đó, tạo __init__.py và custom_tags.py :
Trong custom_tags.py tạo một chức năng thẻ tùy chỉnh cung cấp quyền truy cập vào một khóa tùy ý trong hằng số cài đặt :
from django import template
from django.conf import settings
register = template.Library()
@register.simple_tag
def get_setting(name):
return getattr(settings, name, "")
Để hiểu mã này, tôi khuyên bạn nên đọc phần trên các thẻ đơn giản trong tài liệu Django.
Sau đó, bạn cần làm cho Django biết về thẻ tùy chỉnh này (và bất kỳ bổ sung nào) bằng cách tải tệp này trong bất kỳ mẫu nào mà bạn sẽ sử dụng nó. Giống như bạn cần tải thẻ tĩnh tích hợp:
{% load custom_tags %}
Với nó được tải, nó có thể được sử dụng giống như bất kỳ thẻ nào khác, chỉ cần cung cấp cài đặt cụ thể mà bạn cần trả lại. Vì vậy, nếu bạn có biến BUILD_VERSION trong cài đặt của mình:
{% get_setting "BUILD_VERSION" %}
Giải pháp này sẽ không hoạt động với các mảng, nhưng nếu bạn cần rằng bạn có thể đưa ra nhiều logic trong các mẫu của mình.
Lưu ý: Một giải pháp sạch hơn và không an toàn hơn có lẽ là tạo một bộ xử lý ngữ cảnh tùy chỉnh nơi bạn thêm các cài đặt bạn cần vào một ngữ cảnh có sẵn cho tất cả các mẫu. Bằng cách này, bạn giảm nguy cơ xuất các cài đặt nhạy cảm trong các mẫu của mình do nhầm lẫn.
Thêm mã này vào một tệp có tên context_processors.py
:
from django.conf import settings as django_settings
def settings(request):
return {
'settings': django_settings,
}
Và sau đó, trong tệp cài đặt của bạn, bao gồm một đường dẫn như 'speedy.core.base.context_processors.settings'
(với tên ứng dụng và đường dẫn của bạn) trong 'context_processors'
cài đặt trong TEMPLATES
.
(Bạn có thể xem ví dụ cài đặt / base.py và context_processors.py ).
Sau đó, bạn có thể sử dụng cài đặt cụ thể trong bất kỳ mã mẫu nào. Ví dụ:
{% if settings.SITE_ID == settings.SPEEDY_MATCH_SITE_ID %}
Cập nhật: Đoạn mã trên hiển thị tất cả các cài đặt cho các mẫu, bao gồm cả thông tin nhạy cảm như của bạn SECRET_KEY
. Một hacker có thể lạm dụng tính năng này để hiển thị thông tin như vậy trong các mẫu. Nếu bạn muốn chỉ hiển thị các cài đặt cụ thể cho các mẫu, thay vào đó hãy sử dụng mã này:
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
. Một hacker có thể lạm dụng tính năng này để hiển thị thông tin như vậy trong các mẫu.
Ví dụ trên từ bchhun là tốt, ngoại trừ việc bạn cần xây dựng rõ ràng từ điển ngữ cảnh của mình từ settings.py. Dưới đây là một ví dụ KHÔNG GIỚI HẠN về cách bạn có thể tự động xây dựng từ điển ngữ cảnh từ tất cả các thuộc tính chữ hoa của settings.py (re: "^ [A-Z0-9 _] + $").
Ở cuối phần cài đặt:
_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',
...
)
Nếu ai đó tìm thấy câu hỏi này giống như tôi, thì tôi sẽ đăng giải pháp của tôi lên Django 2.0:
Thẻ này gán một số giá trị biến cài đặt cho biến của mẫu:
Sử dụng: {% 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 %}
Xem tài liệu của Django cách tạo thẻ mẫu tùy chỉnh tại đây: https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/
{% if settings_debug %}
{% if settings_debug == True %}
theo đề xuất của bạn{% if settings_debug %}
Nếu sử dụng chế độ xem dựa trên lớp:
#
# 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 }}
Cả IanSR và bchhun đều đề xuất ghi đè TEMPLATE_CONTEXT_PROCESSORS trong cài đặt. Xin lưu ý rằng cài đặt này có mặc định có thể gây ra một số điều khó hiểu nếu bạn ghi đè lên mà không đặt lại mặc định. Mặc định cũng đã thay đổi trong các phiên bản gần đây của Django.
https://docs.djangoproject.com/en/1.3/ref/sinstall/#template-context- Processors
TEMPLATE_CONTEXT_PROCESSORS mặc định:
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")
Nếu chúng ta so sánh ngữ cảnh với các thẻ mẫu trên một biến duy nhất, thì việc biết tùy chọn hiệu quả hơn có thể có lợi. Tuy nhiên, tốt hơn hết bạn chỉ nên nhúng vào các cài đặt từ các mẫu cần biến đó. Trong trường hợp đó, sẽ không có ý nghĩa gì khi chuyển biến vào tất cả các mẫu. Nhưng nếu bạn đang gửi biến vào một mẫu chung như mẫu base.html, thì sẽ không có vấn đề gì vì mẫu base.html được hiển thị trên mỗi yêu cầu, vì vậy bạn có thể sử dụng một trong hai phương thức.
Nếu bạn quyết định sử dụng tùy chọn thẻ mẫu, thì hãy sử dụng đoạn mã sau vì nó cho phép bạn chuyển một giá trị mặc định vào, chỉ trong trường hợp biến trong câu hỏi không được xác định.
Ví dụ: get_from_sinstall my_variable as my_context_value
Ví dụ: get_from_sinstall my_variable my_default là 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)