Djangoのテンプレートからsettings.pyの定数にアクセスできますか?


367

テンプレートからアクセスできるようにしたいものがsettings.pyにありますが、その方法がわかりません。私はすでに試しました

{{CONSTANT_NAME}}

しかし、それはうまくいかないようです。これは可能ですか?


すべての回答に設定を渡す方法をお探しの場合は、コンテキストプロセッサに関するbchunnの回答をご覧ください
Zags

1
@jkbrztからの回答は、この問題を迅速かつ簡単に解決する事前にパッケージ化されたソリューションです。今後の読者は、承認された回答についてこのstackoverflow.com/a/25841039/396005を確認する必要があります
Bron Davies

回答:


183

Djangoは、settings.MEDIA_URLdjangoの組み込みの一般的なビューを使用する場合、または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 }}


66
RequestContextを使用して追加される特定の値は、TEMPLATE_CONTEXT_PROCESSORSの値に依存することに注意してください。したがって、あらゆる場所で追加の値を渡したい場合は、独自のコンテキストプロセッサを記述して、TEMPLATE_CONTEXT_PROCESSORSに追加します。
カールマイヤー

一貫性に関するポイント、一般的なビュー、および多くのコアアプリとContribアプリでは、追加のコンテキストはextra_contextと呼ばれ、多くの場合、ビューの引数に含まれます。
2009年

「Djangoは、settings.MEDIA_URLなど、頻繁に使用される特定の設定定数へのアクセスをテンプレートに提供します。」これはDjango 1.3では機能しないようですが、おそらく間違って使用しています。この機能のドキュメントはありますか?
SystemParadox

1
@asofyanはい、カスタムテンプレートコンテキストプロセッサを作成し、settings.pyのTEMPLATE_CONTEXT_PROCESSORSに追加します。
Paolo

14
django-settings-exportすべてのビューでこのコードを書く必要がないように注意してください。
qris

441

それがすべてのリクエストとテンプレートに必要な値である場合は、コンテキストプロセッサを使用する方が適切です。

方法は次のとおりです。

  1. 作る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}
  2. コンテキストプロセッサをsettings.pyファイルに追加します。

    TEMPLATES = [{
        # whatever comes before
        'OPTIONS': {
            'context_processors': [
                # whatever comes before
                "your_app.context_processors.admin_media",
            ],
        }
    }]
  3. RequestContextビューで使用して、テンプレートにコンテキストプロセッサを追加します。renderショートカットは、これを自動的に行います。

    from django.shortcuts import render
    
    def my_view(request):
        return render(request, "index.html")
  4. そして最後に、テンプレートで:

    ...
    <a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a>
    ...

32
@MarkEsselこれらのフープは、RequestContext関数を使用する限り、作成するすべてのビューで変数にアクセスできるように作成されています。すべてのビューで設定変数をいつでも手動でフェッチできます。古き良きコピー&ペーストではなく、いつでも再利用可能なコンテキストプロセッサを選択します。
bchhun 2012年

5
可能な限りコピー/貼り付けをしないように最善を尽くしています。(プロジェクト内の)すべてのアプリがcontext_processor.pyを必要としますか。それらすべてに対して1つのcontext_processorを構築する方法はありますか?
マークエッセル2012年

10
@bchhun私がテストしたばかり(Django 1.3):アプリ間でコンテキストプロセッサを共有することはうまくいきます。:-)私はcontext_process.py自分のsettings.pyファイルのすぐ隣に置き"context_processors.admin_media"TEMPLATE_CONTEXT_PROCESSORSリストに追加しました。また、TEMPLATE_CONTEXT_PROCESSORSのデフォルト値が空ではないという事実についての回答にメモを追加することをお勧めします。そのため、既存のコードがそれらのデフォルトのコンテキストプロセッサによって設定された値のいずれかを使用する場合、それらを追加しない限り機能しません。リストに明示的に。
MiniQuark 2013年

5
@MarkEsselまったく苦痛はありません-彼はすべてを綴っています。実際には、わずか6行の短い行(ステップ1および2)です。いずれにしても、ほとんどのテンプレートには手順3と4または同等の手順が必要です。
Rick Westera、

2
Django 1.3以降では、renderショートカットを使用して、RequestContext
yndolok

269

最も単純なアプローチは、単一のカスタムテンプレートタグであることがわかります。

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" %}

17
テンプレートの設定にオンデマンドでアクセスできるのが気に入っています。これにより、エレガントにそれを実現できます。テンプレートでさまざまな設定を頻繁に使用する場合、これは他の回答よりもはるかに優れています。1)受け入れられた回答は、クラスベースのビューと互換性がないか、不格好です。2)過度に投票されたテンプレートコンテキストプロセッサソリューションでは、個別の設定(またはすべて)を指定する必要があり、テンプレートをレンダリングするすべてのリクエストに対して実行されます-非効率的です!3)上記のより複雑なタグよりも単純です。
ベンロバーツ

16
@BenRoberts私はこれがエレガントな解決策であることに同意します...しかし、すべてを行う単一の開発者がいる小さなプロジェクトのためだけです。設計と開発に別の人/チームがある場合、このソリューションはおそらく最悪です。デザイナーがこのタグを次のようなもので悪用するのを防ぐにはどうすればよいです{% settings_value "DATABASES" %}か?このユースケースでは、そもそもテンプレートで設定を使用できない理由を明らかにする必要があります。
mkoistinen 2013年

23
「私たちはみなここで大人に同意しています」
frnhr '22

11
初心者であることを許してください。このコードはどこに配置しますか?Views.py?または新しいファイルに?
Noel Llevares、2014

13
他の人にわかりやすくするために、次のことを行う必要があります。1)templatetagsアプリ内に空の__init__.pyファイルとこのコードを含むフォルダーをフォルダー内に作成settings.pyします。2)テンプレートに追加{% load settings %}した新しいタグを使用します!
damio

95

チェックアウト django-settings-export(免責事項:私はこのプロジェクトの作成者です)。

例えば...

$ pip install django-settings-export

settings.py

TEMPLATES = [
    {
        'OPTIONS': {
            'context_processors': [
                'django_settings_export.settings_export',
            ],
        },
    },
]

MY_CHEESE = 'Camembert';

SETTINGS_EXPORT = [
    'MY_CHEESE',
]

template.html

<script>var MY_CHEESE = '{{ settings.MY_CHEESE }}';</script>

1
そして、あなたの意見では、あなたが使用する必要があることに注意renderしていないrender_to_response
エヴェレットToews

テンプレートの設定から値を読み取るための同様の要件がありますが、設定ファイルに「django_settings_export.settings_export」を追加すると500エラーが発生します。ここで何が間違っているのかを提案できますか
Piyush Sahu

3
それは2019年で、私のプロジェクトで使用しています。ありがとう!
sivabudh

1
@sivabudhに同意します。これは私にとっても最善の解決策です。1。集中化されているため、追加のフォルダーやファイルは必要ありません。2。多くのアプリケーションの参照を取得するのに非常に役立つテンプレートに設定名前空間が表示されます。
ywiyogo

46

これを行う別の方法は、設定から値を釣り上げることができるカスタムテンプレートタグを作成することです。

@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" %}

コンテキストプロセッサのフープを飛び越えることなく、任意のページに印刷する。


6
コードを変更せずにドロップインとして機能するため、これは最もエレガントなソリューションだと思います。
空飛ぶ羊

1
あなたは(あなたはいくつかの場所であなたのアプリケーションを編集する必要があることどの手段)つのタグを追加し、それを使用する代わりに、コンテキストプロセッサを追加するので:あなたが変更されていないアプリケーションの残りの部分を残すことができる
飛んで羊を

2
@Mark-produi / src / produi / template_utils / templatetags / custom_template_filters.pyでtemplate_utilsはsettings.py INSTALLED_APPSから参照されます-docs.djangoproject.com/en/dev/howto/custom-template-tags
fadedbee

ヘルプクリスに感謝し、custom_template_filtersを含むtemplatetagsサブディレクトリを持つmutilアプリを追加しました。homepage.htmlで引き続きエラーが発生する "無効なブロックタグ: 'value_from_settings'、予期された 'endblock'または 'endblock banner'"
Mark Essel

これは、「明示的は暗黙的より優れている」とは反対であり、公開する設定を正確に選択するコンテキストデコレータバージョンを使用します。
sjh

29

単純なサイトではクリーンで効果的であるため、ベリスラフのソリューションが好きです。私が気に入らないのは、すべての設定定数を公開することです。だから私がやったことはこれでした:

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" %}

これにより、名前を付けていない定数がテンプレートで使用されないように保護します。本当に凝ったものにしたい場合は、設定でタプルを設定し、さまざまなページ、アプリ、または領域に複数のテンプレートタグを作成できます。必要に応じてローカルタプルと設定タプルを組み合わせてから、リスト内包を行い、値が受け入れ可能かどうかを確認します。
私は同意します。複雑なサイトでは、これは少し単純化していますが、テンプレートで普遍的に持つとよい値があり、これはうまく機能しているようです。オリジナルのアイデアを提供してくれたベリスラフに感謝します。


5
なぜ単純ではないのかif name in ALLOWABLE_VALUES: ...
frnhr 2014年

私は賢いと思っていて、サブストリングが設定変数をトリガーしないようにしたかったので。;-)リターンはおそらく次のようになります:return getattr(settings、is_allowable、 '')
MontyThreeCard

5
疑問に思う人のために明確にするために:'val' in ('val_first', 'second_val',)False、ここでは部分文字列の問題はありません。
frnhr 2014

2
これをifステートメントでどのように使用できますか?DEBUG値を確認したい
AJ

再付きバージョンを必要とする誰かが含まれている場合gist.github.com/BrnoPCmaniak/632f56ddb907108b3d43fa862510dfca
フィリップDobrovolný

12

私はクリスデューの答え(あなた自身のタグを作成するため)を少し改善しました

まず、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}}です。


12

Django 2.0以降で、これを解決するカスタムテンプレートタグを作成するための完全な手順を含む回答を追加する

アプリのフォルダーで、templatetagsという名前のフォルダーを作成します。その中に__init__.pycustom_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ドキュメントの。

次に、使用するテンプレートにこのファイルをロードして、Djangoにこの(および追加の)カスタムタグを認識させる必要があります。組み込みの静的タグをロードする必要があるのと同じように:

{% load custom_tags %}

読み込まれると、他のタグと同じように使用でき、必要な特定の設定を返すだけです。したがって、設定にBUILD_VERSION変数がある場合:

{% get_setting "BUILD_VERSION" %}

このソリューションは配列では機能しませんが、必要な場合は、テンプレートで多くのロジックを使用する可能性があります。

注:よりクリーンでフェイルセーフなソリューションは、おそらく、必要な設定をすべてのテンプレートで使用可能なコンテキストに追加するカスタムコンテキストプロセッサを作成することです。これにより、誤ってテンプレートに機密設定を出力するリスクを軽減できます。


9

次のコードをこのファイルに追加します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

(たとえば、settings / base.pycontext_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,
    }

1
私は昨日この問題にぶつかり、この投稿を見つけ、次に2人と1つのブログ投稿を見つけ、それらすべてが非常に複雑であると感じました(残念ながら、私はこのページの奥まで到達しなかったので、恥ずかしいです)。それで私は最終的に自分自身をロールすることになりました、それはまさにこのソリューションです。この^^^ 3行の関数と1行のsettings.pyの変更があったときに、人々がプラグインとロッタ全体のコードを推奨しているのは不思議だったので、戻ってきました。
DXM

@DXMありがとうございます!
スピーディマッチ

実際、私のソリューションは、などの機密情報を含むすべての設定をテンプレートに公開していますSECRET_KEY。ハッカーはこの機能を悪用して、そのような情報をテンプレートに表示する可能性があります。
スピーディマッチ

回答を更新しました。
スピーディマッチ

ええと...すばらしい、今私のウェブサイトにも同じ問題があります:)しかし...何かが足りないかもしれませんが、問題があると確信していますか?テンプレートは基本的にあなたのウェブサイトのソースコードと同じですよね?これらはサーバー側に格納され、フロントエンドから直接アクセスできません。ハッカーがテンプレートを変更できる場合、その時点で任意の.pyファイルを変更する可能性があります。
DXM

8

上記のbchhunの例は、settings.pyからコンテキストディクショナリを明示的に構築する必要があることを除いて、優れています。以下は、settings.pyのすべての大文字の属性からコンテキストディクショナリを自動構築する方法のテストされていない例です(re: "^ [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',
...
)

8

私のように誰かがこの質問を見つけたら、Django 2.0で動作する私の解決策を投稿します。

このタグは、いくつかのsettings.py変数値をテンプレートの変数に割り当てます。

使用法: {% get_settings_value template_var "SETTINGS_VAR" %}

app / templatetags / my_custom_tags.py:

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/


1
{% if settings_debug %}
user66081

@ user66081に感謝!{% if settings_debug == True %}あなたの提案に変更{% if settings_debug %}
NullIsNot0

7

クラスベースのビューを使用している場合:

#
# 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 }}

3

これがDjango 1.3の最も簡単なアプローチであることがわかりました。

  1. views.py

    from local_settings import BASE_URL
    
    def root(request):
        return render_to_response('hero.html', {'BASE_URL': BASE_URL})
  2. hero.html

    var BASE_URL = '{{ JS_BASE_URL }}';

1

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")

1

単一の変数のコンテキストタグとテンプレートタグを比較する場合、より効率的なオプションを知ることは有益です。ただし、その変数を必要とするテンプレートからのみ設定にディップした方がよい場合があります。その場合、変数をすべてのテンプレートに渡すことは意味がありません。ただし、base.htmlテンプレートなどの一般的なテンプレートに変数を送信する場合、base.htmlテンプレートはすべてのリクエストでレンダリングされるため、どちらの方法でも使用できるため、問題にはなりません。

テンプレートタグオプションを使用する場合は、変数in inquestionが未定義だった場合に備えて、デフォルト値を渡すことができるため、次のコードを使用します。

例:get_from_settings my_variable as my_context_value

例:get_from_settings my_variable my_default as 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)

またはSITE_EXTRA_CONTEXT_DICTファイナルウェアで使用してそれを行うことができます。
un33k 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.