views:

80

answers:

2

I am reading the definitive guide to django and am in Chapter 4 on template inheritance. It seems that I am not doing something as elegant as should be possible as I am having to duplicate some code for the context to appear when calling the child view. Here is the code in views.py:

def homepage(request):
    current_date = datetime.datetime.now()
    current_section = 'Temporary Home Page'
    return render_to_response("base.html", locals())
def contact(request):
    current_date = datetime.datetime.now()
    current_section = 'Contact page'
    return render_to_response("contact.html", locals())

It seems redundant to have to include the current_date line in each function.

Here is the base html file that homepage calls:

<html lang= "en">
<head>
    <title>{% block title %}Home Page{% endblock %}</title>
</head>
<body>
    <h1>The Site</h1>
    {% block content %}
        <p> The Current section is {{ current_section }}.</p>
    {% endblock %}

    {% block footer %}
    <p>The current time is {{ current_date }}</p>
    {% endblock %}
</body>
</html>

and a child template file:

{% extends "base.html" %}

{% block title %}Contact{% endblock %}

{% block content %}
<p>Contact information goes here...</p>
    <p>You are in the section {{ current_section }}</p>
{% endblock %}

If I don't include the current_date line when calling the child file, where that variable should appear is blank.

+2  A: 

You can pass a variable to every template by using Context Processors like so:

1. Changes in settings.py

First, you will need to add your custom Context Processor to your settings.py:

# settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
                               'myapp.context_processors.default',
                               'django.core.context_processors.auth', 
)

From that you can derive that you will need to create a module called context_processors.py and place it inside your app's folder. That module will need to declare a function called 'default', but this is arbitrary. You can choose whichever name you prefer.

2. Creating the Context Processor

# context_processors.py

from datetime import datetime
from django.conf import settings  # this is a good example of extra
                                  # context you might need across templates
def default(request):

    # you can declare any variable that you would like and pass 
    # them as a dictionary to be added to each template's context like so:
    return dict(
        example = "This is an example string.", # don't forget the commas!
        current_date = datetime.now(),                
        MEDIA_URL = settings.MEDIA_URL, # just for the sake of example
    )



3. Adding the extra context to your views

The final step is to replace the usual template parsing by one that includes the variables from that context processor. In order to achieve this, you will have to make a small modification to your views:

# old views.py
def homepage(request):
    current_date = datetime.datetime.now()
    current_section = 'Temporary Home Page'
    return render_to_response("base.html", locals())

def contact(request):
    current_date = datetime.datetime.now()
    current_section = 'Contact page'
    return render_to_response("contact.html", locals())


# new views.py
from django.template import RequestContext

def homepage(request):
    current_section = 'Temporary Home Page'
    return render_to_response("base.html", locals(),
                              context_instance=RequestContext(request))

def contact(request):
    current_section = 'Contact page'
    return render_to_response("contact.html", locals(),
                              context_instance=RequestContext(request))
airstrike
Great. This is exactly what I was looking for. Also thanks for adding the info about from django.conf import settings. The detailed explanation was perfect.
Steve