Here's how to dodge some of the more obvious template pitfalls: == Debugging == Not a pitfall, but a tip: Use {% debug %} in a template block if you want to know what is defined and can be used in a template. The debug output is pretty ugly unless you look at it through View Source, or you can do it this way: {{{ {% filter linebreaks %} {% debug %} {% endfilter %} }}} == Anonymity == {{{user.is_anonymous}}} is a method, not an attribute, which makes it hard to test against in a template. Set your own context variable {{{is_anonymous}}}, instead. == Context variables and template inheritance == To solve ''Anonymity'' above, it's handy to define a method each view can call to fill in its {{{Context}}} with the right variables. If you're inheriting templates, you should also do the same with the method. I've ended up with an {{{app_vars}}} method in each app's views module which calls {{{site_vars}}} in the site. {{{site_vars}}} goes in {{{sitename/views/sitename.py}}} if you're trying to match the default shape of the application namespace, or in {{{sitename/views.py}}} if you're flattening it: {{{ def site_vars(request, **kwargs): """Determine context variables for the site's base template.""" user = request.user is_anonymous = user.is_anonymous() if is_anonymous: username = name = '(anonymous)' else: username = user.username name = user.get_full_name() if not name: name = username vars = { 'is_anonymous': is_anonymous, 'name': name, 'username': username, } vars.update(kwargs) return vars }}} A custom version of {{{app_vars}}} goes in each {{{sitename/apps/appname/views/appname.py}}} (or, if you're flattening the namespace, {{{sitename/apps/appname/views.py}}}): {{{ def app_vars(request, **kwargs): """Determine context variables for the application and site base templates.""" vars = {} # set your app variables here vars.update(site_vars(request, **kwargs)) return vars }}} The keyword arguments let you define additional useful variables for your page without having to further manipulate the dictionary: just keep piling on the arguments to {{{app_vars}}}. Let's say your base template likes to have a {{{title}}} variable available to it: {{{ def index(request): """View the appname index.""" # Customise the app variables the hard way vars = app_vars(request) vars['title'] = "Index" # Or, the easy way vars = app_vars(request, title="Index") # Load the template, construct the context, and render one against the other: t = template_loader.get_template('appname_index') c = Context(request, vars) return HttpResponse(t.render(c)) }}}