439

I have some stuff in settings.py that I'd like to be able to access from a template, but I can't figure out how to do it. I already tried

{{CONSTANT_NAME}}

but that doesn't seem to work. Is this possible?

Natiq Vahabov
  • 495
  • 4
  • 13
Paul Wicks
  • 62,960
  • 55
  • 119
  • 146
  • If you are looking for how to pass a setting to every answer, look at bchunn's answer about context processors – Zags Mar 31 '15 at 23:32
  • 1
    The answer from @jkbrzt is a pre-packaged solution that solves this problem quickly and easily. Future readers should take a look at this http://stackoverflow.com/a/25841039/396005 over the accepted answer – Bron Davies Sep 27 '16 at 23:59

17 Answers17

522

If it's a value you'd like to have for every request & template, using a context processor is more appropriate.

Here's how:

  1. Make a context_processors.py file in your app directory. Let's say I want to have the ADMIN_PREFIX_VALUE value in every context:

    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. add your context processor to your settings.py file:

    TEMPLATES = [{
        # whatever comes before
        'OPTIONS': {
            'context_processors': [
                # whatever comes before
                "your_app.context_processors.admin_media",
            ],
        }
    }]
    
  3. Use RequestContext in your view to add your context processors in your template. The render shortcut does this automatically:

    from django.shortcuts import render
    
    def my_view(request):
        return render(request, "index.html")
    
  4. and finally, in your template:

    ...
    <a href="{{ ADMIN_MEDIA_URL }}">path to admin media</a>
    ...
    
Flimm
  • 136,138
  • 45
  • 251
  • 267
bchhun
  • 18,116
  • 8
  • 28
  • 31
  • The down side of this approach is that you need to explicitly link the specific settings in settings.py that you want to be available to the context renderer. I could imagine a solution which would use the convention of uppercase attributes in settings.py and auto-build the context. I'll add an example below as a separate response. – IanSR Mar 28 '11 at 13:13
  • 33
    @MarkEssel These hoops are made so the variable is accessible in every View you'll make as long as it uses the RequestContext function. You could always fetch a settings variable manually in every View. I'd choose a reusable Context Processor anytime instead of good ol' Copy & paste. – bchhun Jan 25 '12 at 14:08
  • 6
    doing my best to avoid copy/paste everywhere possible. would each and every app (within a project) require a context_processor.py, is there a way to construct one context_processor for all of them? – Mark Essel Jan 25 '12 at 17:07
  • 1
    @MarkEssel Good question. Without further researches, I'd say it's not possible to share context processors between apps. – bchhun Jan 25 '12 at 17:55
  • 10
    @bchhun I just tested (Django 1.3): sharing a context processor between apps works just fine. :-) I put `context_process.py` just next to my `settings.py` file and added `"context_processors.admin_media"` to my `TEMPLATE_CONTEXT_PROCESSORS` list. Also, you may want to add a note in your answer about the fact that TEMPLATE_CONTEXT_PROCESSORS's default value is not empty, so if any existing code uses any of the values set by those default context processors, they won't work unless you add them back to the list explicitly. – MiniQuark Mar 05 '13 at 18:05
  • 5
    @MarkEssel Not painful at all - he's just spelled everything out. It's really only 6 short lines (steps 1 & 2). Steps 3 & 4 or their equivalent are required for most templates anyway. – Rick Westera Jan 20 '14 at 04:28
  • MiniQuark & @Rrrrrrrrrk ah, excellent. Haven't worked with django since this comment. Thanks for replying though! – Mark Essel Jan 20 '14 at 21:15
  • @bchhun this still isn't quite as simple as just being able to use a config variable directly in a template; e.g. for django-registration I'd like to be able to add the protocol (http or https) as a configurable parameter in the activation email template, and the simplest way would be to make it a setting. Instead I'd have to work out how to use a different context processor with a third-party app. Or have I misunderstood? – Rob Grant Jul 17 '14 at 12:27
  • A little convoluted to setup initially, but this is indeed a good solution – user Aug 17 '14 at 09:38
  • 2
    As of Django 1.3, you can use the `render` shortcut to avoid having to explicitly including RequestContext: https://docs.djangoproject.com/en/1.6/topics/http/shortcuts/#render – yndolok Aug 20 '14 at 23:38
  • I'm finding the writing-your-own-context-processors link here: https://docs.djangoproject.com/en/1.8/ref/templates/api/#writing-your-own-context-processors (the current link from "context processor" in the answer yields a Page not found) – Marjorie Roswell Apr 07 '15 at 16:52
  • Worked for me, without step 3! Note that since django 1.8 you need to put the context processor in a different place, like this: `TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': ..., 'APP_DIRS': False, 'OPTIONS': { 'context_processors': ( "django.contrib.auth.context_processors.auth", ... "my_app.context_processors.admin_media", ) 'loaders':..., }, }, ] ` – oriadam Dec 30 '15 at 22:54
  • 1
    Great stuff! For the record in `context_processors.py` you can also do `return {'ADMIN_MEDIA_URL': settings.ADMIN_MEDIA_PREFIX, 'ANOTHER_KEY':'another value'}` and `{{ANOTHER_KEY}` is also accessible – citynorman Dec 19 '17 at 02:53
  • By far the best answer to this question, granted I was only looking for an answer because I was looking for an even easier way... I would like to add one word of caution here. context_processors are blocking, so doing anything more than simple calculation or returning a string could slow each request down especially if you're not limiting the use of the context processor to specific endpoints. – AppHandwerker Sep 04 '20 at 18:32
347

I find the simplest approach being a single custom template tag:

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

Usage:

{% settings_value "LANGUAGE_CODE" %}
Antoine Pinsard
  • 33,148
  • 8
  • 67
  • 87
Berislav Lopac
  • 16,656
  • 6
  • 71
  • 80
  • 20
    I love having on-demand access to any setting in templates, and this provides that elegantly. This is really much better than the other answers if you'll frequently be using various settings in your templates: 1) The accepted answer is incompatible or clunky with class-based views. 2) With the over-voted template context processor solution, you'd have to specify individual settings (or all) and it would run for every single request that renders a template--inefficient! 3) Its simpler than the more complex tag above. – B Robster Aug 19 '12 at 06:49
  • 19
    @BenRoberts I do agree that this is an elegant solution... but only for tiny projects with a single developer that does everything. If you have separate people/teams for design and development, then this solution is probably **the worst**. What's to stop the designer from abusing this tag with something like: `{% settings_value "DATABASES" %}`? This use-case should make it obvious why settings isn't available in templates to begin with. – mkoistinen May 18 '13 at 11:30
  • 10
    Well you can always expand my example to include a list of the settings you allow to be called this way; if one calls an unlisted one, just return a simple empty string. – Berislav Lopac May 18 '13 at 15:13
  • @mkoistinen I think you make some good points. I work with a small team, and code review takes care of any blunders like the one you mention (and I've seen nothing like it). With an open source project or large team, I can see how the calculus would be different. If the team grows to the point where the risk becomes real, I'd prefer to just add settings directly to context on an ad hoc basis (the second code snippet in accepted answer) over using a Context Processor that gets run for every single request... – B Robster May 29 '13 at 18:16
  • You can repeat the code for each exposed setting def LANGUAGE_CODE(): return settings.LANGUAGE_CODE to prevent abuse. – laffuste Aug 15 '13 at 02:35
  • 30
    "We're all consenting adults here" – frnhr Mar 22 '14 at 09:49
  • 12
    Pardon me for being a newbie. Where do you put this code? Views.py? Or on a new file? – Noel Llevares Jun 06 '14 at 22:54
  • 1
    @Berislav Lopac great example, but I think modifying it to only allow whitelisted settings would make it even better. – stupidbodo Apr 10 '15 at 07:10
  • 22
    to be clear for other people, you need to: 1) create a `templatetags` folder inside your app with an empty `__init__.py` file and this code as `settings.py` inside that folder. 2)in your template you add `{% load settings %}` and then use your new tag ! – damio Oct 25 '16 at 13:08
  • 6
    what if you need an `if` on that value? how could you use it? – EsseTi Apr 19 '18 at 12:31
  • For anyone wondering why above doesn't work, getting the error: "TemplateSyntaxError: 'settings_value' is not a registered tag library" -> you need to reload your server. – angelos_lex Jun 18 '19 at 20:56
  • The moderator removed all my edits to help make this post more clear. To get this to work you need to follow @damio instructions. – Dan Walters Nov 27 '19 at 13:09
  • The answer assumes that one is familiar with Django enough to know how to set custom template tags. For clarity, I have added the link to the relevant documentation page. – Berislav Lopac Nov 27 '19 at 22:07
  • 1
    Is there a way to use this variable for logic. {% if settings_value "DEV" == True %} results in: Unused ''DEV'' at end of if expression. – Dan Walters Dec 09 '19 at 10:42
  • 1
    For that you will need to set up a variable: https://docs.djangoproject.com/en/3.0/howto/custom-template-tags/#setting-a-variable-in-the-context – Berislav Lopac Dec 10 '19 at 12:58
  • In addition to @damio Don't forget to restart your dev server to load the new templatetag. – Jean Zombie May 28 '20 at 10:53
  • For how to be able to use the custom tag you can check this answer https://stackoverflow.com/a/70981469/8668847 – Baraa Al-jabali Dec 21 '22 at 11:08
  • Another way to make the tag value available in context for use in `if` conditions (as requested by @esseti and @dan-walters) is using the `as` keyword, e.g. `{% settings_value "LANGUAGE_CODE" as lang_code %}` followed by `{% if lang_code == ... %}` – djvg Mar 01 '23 at 09:18
198

Django provides access to certain, frequently-used settings constants to the template such as settings.MEDIA_URL and some of the language settings if you use django's built in generic views or pass in a context instance keyword argument in the render_to_response shortcut function. Here's an example of each case:

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

These views will both have several frequently used settings like settings.MEDIA_URL available to the template as {{ MEDIA_URL }}, etc.

If you're looking for access to other constants in the settings, then simply unpack the constants you want and add them to the context dictionary you're using in your view function, like so:

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)

Now you can access settings.FAVORITE_COLOR on your template as {{ favorite_color }}.

prairiedogg
  • 6,323
  • 8
  • 44
  • 52
  • 71
    It's worth noting that the specific values added by using a RequestContext is dependent on the value of TEMPLATE_CONTEXT_PROCESSORS. Thus if you want additional values passed in everywhere, just write your own context processor and add it to TEMPLATE_CONTEXT_PROCESSORS. – Carl Meyer Jan 26 '09 at 19:12
  • A point on consistency, in the generic views, and many of the core and contrib apps, additional context is called extra_context, and very often it is included in the view's arguments. – Soviut Jun 01 '09 at 01:33
  • "Django provides access to certain, frequently-used settings constants to the template such as settings.MEDIA_URL". This doesn't appear to work in Django 1.3, although I'm probably using it wrong. Is there any documentation for this feature? – SystemParadox Oct 28 '11 at 10:46
  • is there any tips to pass settings variables on _every_ template? – asofyan May 01 '13 at 10:45
  • 1
    @asofyan yes, add create a custom template context processor and add to TEMPLATE_CONTEXT_PROCESSORS in settings.py. – Paolo Oct 08 '13 at 15:31
  • 17
    Do look at [`django-settings-export`](https://github.com/jakubroztocil/django-settings-export) to avoid the need to write this code in every view. – qris Nov 14 '14 at 17:28
112

Check out django-settings-export (disclaimer: I'm the author of this project).

For example...

$ 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>
Bob Stein
  • 16,271
  • 10
  • 88
  • 101
Jakub Roztocil
  • 15,930
  • 5
  • 50
  • 52
  • 1
    And note that in your views you need to use [`render`](https://docs.djangoproject.com/en/1.11/topics/http/shortcuts/#render) and not `render_to_response` – Everett Toews Jul 16 '17 at 23:09
  • I have similar requirement to read values from setting in templates but I am getting 500 error when I add 'django_settings_export.settings_export' in setting file.Can you suggest what am i doing wrong here – Piyush Sahu Jan 18 '18 at 05:47
  • 2
    I agree with @sivabudh. This is for me also the best solution because 1. It is centralized which means that I don't need extra folder and files, 2. I can see the settings namespace in my template which is very helpful to get the references of many application. – ywiyogo Apr 25 '19 at 11:50
50

Another way to do this is to create a custom template tag which can let you fish values out of the settings.

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

You can then use:

{% value_from_settings "FQDN" %}

to print it on any page, without jumping through context-processor hoops.

fadedbee
  • 42,671
  • 44
  • 178
  • 308
  • 6
    i think this is the most elegant solution, as it works as dropin without changing code. – flying sheep Oct 05 '11 at 07:51
  • 1
    that you can leave the rest of your application unaltered: you add one tag and use it, instead of having to add context processors (which means that you have to edit your application at several places) – flying sheep Dec 11 '11 at 12:04
  • 2
    @Mark - in produi/src/produi/template_utils/templatetags/custom_template_filters.py template_utils is referenced from settings.py INSTALLED_APPS - also see https://docs.djangoproject.com/en/dev/howto/custom-template-tags/ – fadedbee Jan 26 '12 at 16:44
  • appreciate the help chris, added a mutil app with a templatetags subdirectory including custom_template_filters. Still getting an error in homepage.html "Invalid block tag: 'value_from_settings', expected 'endblock' or 'endblock banner'" – Mark Essel Jan 27 '12 at 19:26
  • I think this goes against "explicit is better than implicit", using the context decorator version you choose exactly what settings to expose. – sjh Feb 28 '12 at 15:30
  • So far I am using this solution except I cannot use getattr on the settings object properly. – rhigdon Mar 28 '12 at 02:14
  • @chrisdew not a problem. For my particular issue there was a handy database entry for the app name accessible through the admin. I finished up a basic app in jan-feb, and switched back to Rails. It was a fun experience and I dig python, although I'm not enamored with django. – Mark Essel Apr 04 '12 at 16:36
  • I don't think there's a need for `template.Variable()` in this example. The use of `str()` on an instance of `Variable` simply returns the value that was given to the constructor, verbatim. – Michael Wehner Apr 27 '12 at 06:33
  • 2
    I spent some time making things work properly as proposed in this answer... Firstly, you need to create a new folder in your app's folder called `templatetags` with empty `__init__.py` in it. Then, create a `custom_tags.py` there with the code above (don't forget `register = template.Library()`. Secondly, register in `INSTALLED_APPS = [..., 'your_app.templatetags', ..]`. Thirdly, in a html-template header you need to load module:`{% load custom_tags %}`. And THEN it will work: `{% value_from_settings "A_PARAMETER_FROM_SETTINGS" %}` – Constantine Kurbatov Jun 10 '21 at 21:36
33

I like Berislav's solution, because on simple sites, it is clean and effective. What I do NOT like is exposing all the settings constants willy-nilly. So what I ended up doing was this:

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 ''

Usage:

{% settings_value "CONSTANT_NAME_1" %}

This protects any constants that you have not named from use in the template, and if you wanted to get really fancy, you could set a tuple in the settings, and create more than one template tag for different pages, apps or areas, and simply combine a local tuple with the settings tuple as needed, then do the list comprehension to see if the value is acceptable.
I agree, on a complex site, this is a bit simplistic, but there are values that would be nice to have universally in templates, and this seems to work nicely. Thanks to Berislav for the original idea!

mrmuggles
  • 2,081
  • 4
  • 25
  • 44
MontyThreeCard
  • 821
  • 9
  • 14
  • 5
    why not simply `if name in ALLOWABLE_VALUES: ...` – frnhr Mar 22 '14 at 09:53
  • Because I thought I was being clever, and wanted to prevent sub-strings from triggering the settings var. ;-) The return should probably be: return getattr(settings, is_allowable, '') – MontyThreeCard Apr 04 '14 at 21:41
  • 5
    Just to clarify for anyone who's wondering: `'val' in ('val_first', 'second_val',)` is `False`, no substring problem here. – frnhr Apr 04 '14 at 21:44
  • 2
    How can i use this in `if` statement? i want to check the `DEBUG` value – A.J. May 20 '15 at 13:03
  • If someone would need version with re included https://gist.github.com/BrnoPCmaniak/632f56ddb907108b3d43fa862510dfca – Filip Dobrovolný Jan 05 '17 at 21:31
18

Adding an answer with complete instructions for creating a custom template tag that solves this, with Django 2.0+

In your app-folder, create a folder called templatetags. In it, create __init__.py and custom_tags.py:

Custom tags folder structure

In the custom_tags.py create a custom tag function that provides access to an arbitrary key in the settings constant:

from django import template
from django.conf import settings

register = template.Library()

@register.simple_tag
def get_setting(name):
    return getattr(settings, name, "")

To understand this code I recommend reading the section on simple tags in the Django docs.

Then, you need to make Django aware of this (and any additional) custom tag by loading this file in any template where you will use it. Just like you need to load the built in static tag:

{% load custom_tags %}

With it loaded it can be used just like any other tag, just supply the specific setting you need returned. So if you have a BUILD_VERSION variable in your settings:

{% get_setting "BUILD_VERSION" %}

This solution will not work with arrays, but if you need that you might be putting to much logic in your templates.

Note: A more clean and failsafe solution would probably be to make a custom context processor where you add the settings you need to a context available to all templates. This way you reduce the risk of outputting sensitive settings in your templates by mistake.

Andreas Bergström
  • 13,891
  • 5
  • 59
  • 53
17

Add this code to a file called context_processors.py:

from django.conf import settings as django_settings


def settings(request):
    return {
        'settings': django_settings,
    }

And then, in your settings file, include a path such as 'speedy.core.base.context_processors.settings' (with your app name and path) in the 'context_processors' settings in TEMPLATES.

(You can see for example settings/base.py and context_processors.py).

Then you can use the specific setting in any template code. For example:

{% if settings.SITE_ID == settings.SPEEDY_MATCH_SITE_ID %}

Update: The code above exposes all the settings to templates, including sensitive information such as your SECRET_KEY. A hacker might abuse this feature to display such information in the templates. If you want to expose only specific settings to the templates, use this code instead:

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,
    }
Uri
  • 2,992
  • 8
  • 43
  • 86
  • 2
    I hit this problem yesterday, found this post, then 2 others and a blog post and felt every single one of them were way overly complicated (unfortunately I didn't make it this far down the page, shame on me). So then I ended up rolling my own, which is EXACTLY this solution. I just came back because it was bugging me that people were recommending plugins and a whole lotta code when this ^^^ 3-line function and 1-line change in settings.py. – DXM May 28 '20 at 11:08
  • 1
    Actually my solution exposes all the settings to templates, including sensitive information such as `SECRET_KEY`. A hacker might abuse this feature to display such an information in the templates. – Uri May 28 '20 at 14:49
  • 1
    well... great, now my website has same problem :) But... I might be missing something, however, are we sure there's a problem? Templates are essentially same as source code for your website, aren't they? They are stored server-side and inaccessible directly from front-end. If a hacker can change a template, at that point they could change any .py file. – DXM May 28 '20 at 23:09
  • @DXM Yes, I think in general you are correct. Templates are like source code. And if a hacker has access to your source code, anyway they can get any data from your settings by changing your source code. – Uri May 29 '20 at 04:02
  • 1
    This is by far the easiest and cleanest solution, thank you. I only wish to add a small note that might save time to future readers: you do **not** have to install _speedy.net_ or any other external app for this solution to work. Simply put your _context_processors.py_ file in your main app's directory (e.g. "myapp/") and add the following line to `TEMPLATES.OPTIONS.context_processors` section in _settings.py_: `'myapp.context_processors.settings'` or more in general `'[APP_NAME].context_processors.settings'` where _[APP_NAME]_ should be replaced with the name of your app. – Sal Borrelli Sep 09 '20 at 14:06
13

I improved chrisdew's answer (to create your own tag) a little bit.

First, create the file yourapp/templatetags/value_from_settings.py in which you define your own new tag 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

You can use this tag in your Template via:

{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" %}

or via

{% load value_from_settings %}
[...]
{% value_from_settings "FQDN" as my_fqdn %}

The advantage of the as ... notation is that this makes it easy to use in blocktrans blocks via a simple {{my_fqdn}}.

Community
  • 1
  • 1
pklaus
  • 647
  • 8
  • 21
10

If using a class-based view:

#
# 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 }}
Bill Paetzke
  • 13,332
  • 6
  • 44
  • 46
8

If someone finds this question like I did, then I'll post my solution which works on Django 2.0:

This tag assigns some settings.py variable value to template's variable:

Usage: {% 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)

Your template:

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

See Django's documentation how to create custom template tags here: https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/

NullIsNot0
  • 401
  • 5
  • 7
8

The example above from bchhun is nice except that you need to explicitly build your context dictionary from settings.py. Below is an UNTESTED example of how you could auto-build the context dictionary from all upper-case attributes of settings.py (re: "^[A-Z0-9_]+$").

At the end of 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',
...
)
IanSR
  • 1,415
  • 3
  • 16
  • 18
4

For those who want to use @Berislav's approach (custom template tag) with if tag:

/app/templatetags/my_settings.py:

from django import template
from django.conf import settings

register = template.Library()

@register.simple_tag
def settings_value(name):
    return getattr(settings, name, "")

Template file:

<!-- Load your tags -->
{% load my_settings %}
{% settings_value 'ENABLE_FEATURE_A' as ENABLE_FEATURE_A %}

{% if ENABLE_FEATURE_A %}
<!-- Feature A stuffs -->
{% endif %}
Steve Lukis
  • 420
  • 4
  • 10
3

I found this to be the simplest approach for 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 }}';
    
Michael
  • 1,177
  • 4
  • 20
  • 71
1

A more complete implementation.

/project/settings.py

APP_NAME = 'APP'

/app/templatetags/settings_value.py

from django import template
from django.conf import settings
 
register = template.Library()
 
@register.simple_tag
def settings_value(name):
    return getattr(settings, name, "")

/app/templates/index.html

<!DOCTYPE html>
{% load static %}
{% load settings_value %}
<head>
    <title>{% settings_value "APP_NAME" %}</title>
...
Soliman
  • 441
  • 1
  • 8
  • 15
1

Both IanSR and bchhun suggested overriding TEMPLATE_CONTEXT_PROCESSORS in the settings. Be aware that this setting has a default that can cause some screwy things if you override it without re-setting the defaults. The defaults have also changed in recent versions of Django.

https://docs.djangoproject.com/en/1.3/ref/settings/#template-context-processors

The default 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")
MrOodles
  • 1,856
  • 21
  • 21
1

If we were to compare context vs. template tags on a single variable, then knowing the more efficient option could be benificial. However, you might be better off to dip into the settings only from templates that need that variable. In that case it doesn't make sense to pass the variable into all templates. But if you are sending the variable into a common template such as the base.html template, Then it would not matter as the base.html template is rendered on every request, so you can use either methods.

If you decide to go with the template tags option, then use the following code as it allows you to pass a default value in, just in case the variable in-question was undefined.

Example: get_from_settings my_variable as my_context_value

Example: 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)
vishes_shell
  • 22,409
  • 6
  • 71
  • 81
Val Neekman
  • 17,692
  • 14
  • 63
  • 66
  • Or you can use `SITE_EXTRA_CONTEXT_DICT` in [finalware](https://github.com/un33k/django-finalware#how-to-use) to do it for you. – Val Neekman Mar 26 '16 at 03:27