views:

75

answers:

6

I want to have some constants in a Django Projects. For example, let's say a constant called MIN_TIME_TEST.

I would like to be able to access this constant in two places: from within my Python code, and from within any Templates.

What's the best way to go about doing this?

EDIT: To clarify, I know about Template Context Processors and about just putting things in settings.py or some other file and just importing.

My question is, how do I combine the two approaches without violating the "Don't Repeat Yourself" rule? Based on the answers so far, here's my approach:

I'd like to create a file called global_constants.py, which will have a list of constants (things like MIN_TIME_TEST = 5). I can import this file into any module to get the constants.

But now, I want to create the context processor which returns all of these constants. How can I go about doing this automatically, without having to list them again in a dictionary, like in John Mee's answer?

+2  A: 

Consider putting it into settings.py of your application. Of course, in order to use it in template you will need to make it available to template as any other usual variable.

Vladimir Volodin
+1  A: 

Use context processors to have your constants available in all templates (settings.py is a nice place to define them as Vladimir said).

Luper Rouch
What's a good way of adding them into the context processors after defining them in settings.py? I'd rather not have to repeat the names of all the constants more times.
Edan Maor
All the information is available on the page Luper Rouch linked. You'll have to create a python function which will return a dictionary of vars (that's where you return your constants) and list your function in TEMPLATE_CONTEXT_PROCESSORS setting.
Vladimir Volodin
+4  A: 

Both Luper and Vladimir are correct imho but you'll need both in order to complete your requirements.

  • Although, the constants don't need to be in the settings.py, you could put them anywhere and import them from that place into your view/model/module code. I sometimes put them into the __init__.py if I don't care to have them to be considered globally relevant.

  • a context processor like this will ensure that selected variables are globally in the template scope

    def settings(request):
        """
        Put selected settings variables into the default template context
        """
        from django.conf import settings
        return {
            'DOMAIN':     settings.DOMAIN,
            'GOOGLEMAPS_API_KEY': settings.GOOGLEMAPS_API_KEY,
        }
    

But this might be overkill if you're new to django; perhaps you're just asking how to put variables into the template scope...?

from django.conf import settings

...
# do stuff with settings.MIN_TIME_TEST as you wish

render_to_response("the_template.html", { 
    "MIN_TIME_TEST": settings.MIN_TIME_TEST 
}, context_instance=RequestContext(request)
John Mee
Thanks, that's indeed the direction I want to go. But please see my clarification/other question, i.e. how can I do what you say without having to list all the constants twice?
Edan Maor
Wrap them all into a dictionary then put that dictionary into context. You'll access them via dot notation. eg: {{yourDict.yourConstant}}
John Mee
A: 

In the context processor you can use something like:

import settings

context = {}
for item in dir(settings):
    #use some way to exclude __doc__, __name__, etc..
    if item[0:2] != '__':
        context[item] = getattr(settings, item)
andrei1089
A: 

To build on other people's answers, here's a simple way you'd implement this:

In your settings file:

GLOBAL_SETTINGS = {
    'MIN_TIME_TEST': 'blah',
    'RANDOM_GLOBAL_VAR': 'blah',
}

Then, building off of John Mee's context processor:

def settings(request):
    """
    Put selected settings variables into the default template context
    """
    from django.conf import settings
    return settings.GLOBAL_SETTINGS

This will resolve the DRY issue.

Or, if you only plan to use the global settings occasionally and want to call them from within the view:

def view_func(request):
    from django.conf import settings
    # function code here
    ctx = {} #context variables here
    ctx.update(settings.GLOBAL_SETTINGS)
    # whatever output you want here
Jordan Reiter
A: 

Variant on John Mee's last part, with a little elaboration on the same idea Jordan Reiter discusses.

Suppose you have something in your settings akin to what Jordan suggested -- in other words, something like:

GLOBAL_SETTINGS = {
   'SOME_CONST': 'thingy',
   'SOME_OTHER_CONST': 'other_thingy',
}

Suppose further you already have a dictionary with some of the variables you'd like to pass your template, perhaps passed as arguments to your view. Let's call it my_dict. Suppose you want the values in my_dict to override those in the settings.GLOBAL_SETTINGS dictionary.

You might do something in your view like:

def my_view(request, *args, **kwargs)
    from django.conf import settings
    my_dict = some_kind_of_arg_parsing(*args,**kwargs)
    tmp = settings.GLOBAL_SETTINGS.copy()
    tmp.update(my_dict)
    my_dict = tmp
    render_to_response('the_template.html', my_dict, context_instance=RequestContext(request))

This lets you have the settings determined globally, available to your templates, and doesn't require you to manually type out each of them.

If you don't have any additional variables to pass the template, nor any need to override, you can just do:

render_to_response('the_template.html', settings.GLOBAL_SETTINGS, context_instance=RequestContext(request))

The main difference between what I'm discussing here & what Jordan has, is that for his, settings.GLOBAL_SETTINGS overrides anything it may have in common w/ your context dictionary, and with mine, my context dictionary overrides settings.GLOBAL_SETTINGS. YMMV.

desfido