django: Hacking django object_list to take list of templates

I recently found that you can pass a list or tuple to both django.template.loader.render_to_string and django.shortcuts.render_to_response. These functions iterate over the list of templates and render the first template that exists. The magic lies with the django.template.loader.get_template and select_template functions which take a single template name or list of templates respectively.

This is a great functionality to provide a generic-customized templating architecture where you can pass the name of a specialized template with fallback template name in the last. While working on SeenReport, this feature came really handy as this allowed us to create specialized templates for selected communities with a default template for fallback.

However, I found a slight problem while implementing this architecture. The django.views.generic.list_detail.object_list only accepts a single template name. The solution,

  1. patch the object_list function to use get_template for single template name and select_template for list of templates
  2. find a workaround :)

For reasons beyond the comprehension of common beings, I try not to mess around with django so started looking for a workaround. Going through the definition of object_list, I realized that the object_list receives template_loader as an optional parameter and calls template_loader.get_template to get the passed template. Here is the definition of object_list,

 

def object_list(request, queryset, paginate_by=None, page=None,
        allow_empty=True, template_name=None, template_loader=loader,
        extra_context=None, context_processors=None, template_object_name=’object’,
        mimetype=None):
def object_list(request, queryset, paginate_by=None, page=None,
        allow_empty=True, template_name=None, template_loader=loader,
        extra_context=None, context_processors=None, template_object_name='object',
        mimetype=None):
...
...
    t = template_loader.get_template(template_name)
    return HttpResponse(t.render(c), mimetype=mimetype)
Here is the workaround,
  • pass a list of templates in template_name
  • pass a custom template_loader with a get_template function
Here is the code for my template_loader
def get_template(template_name):
      from django.template import loader
      if type(template_name) == list:
            return loader.select_template(template_name)
      else:
            return loader.get_template(template_name)
The code is self explanatory. If template_name is a list, I call loader.select_template, get_template otherwise. And with that the object_list is seemingly patched to handle list of templates.

No related posts.

Leave a Reply