1

This is similar to this question: How to use method parameters in a Django template?

I understand (and agree with and appreciate) the basic django philosophy of separation of business logic from presentation logic.

However, at times it seems to make DRYness more difficult, and DRY is a practice of even greater gravity, no?

Let's say I have a template that I use for breadcrumb navigation. I re-use (by including) this template over and over for each navigation layer. Nice and dry. Yet I want the template to know which iteration of the nav it is representing.

I swear I remember a method to accomplish this - something like {% include 'llamas'html' | 2 %} but I may be wrong.

If I am, how can I keep this template (and the navigation) DRY without violating the principle of separation of logic?

Community
  • 1
  • 1
jMyles
  • 11,772
  • 6
  • 42
  • 56

2 Answers2

0

Instead of including, you might also extend from a common template that includes or inlines the code for breadcrumbs.

e.g. sometemplate.html:

{% extends "base_with_breadcrumbs.html" %}

Also, if you don't want to have breadcrumbs on some pages, inside the "base_with_breadcrumbs.html" you can wrap the crumbs into an {% if with_crumbs %}...{% endif %} statement.

Inside the base template you can define blocks that may be populated in the derived templates.

Also, take a look at jinja2, it is similar to django, but has many nice features. I've rewritten 50-some templates in jinja for my project and never looked back.

Evgeny
  • 10,698
  • 9
  • 60
  • 70
0

My advice would be to switch to Jinja2. The include tag is mostly the same, but you also have the macro tag which gives you a callable block which can be easily reused with variables.

Some variation on the include tag:

{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}

With macros you can do stuff like this:

{% macro input(name, value='', type='text') -%}
    <input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
{%- endmacro %}

Which can be called like this:

{% import 'forms.html' as forms %}
<dl>
    <dt>Username</dt>
    <dd>{{ forms.input('username') }}</dd>
    <dt>Password</dt>
    <dd>{{ forms.input('password', type='password') }}</dd>
</dl>

Assuming that the file with the macro is forms.html. You can also put the macro in the same file so you won't have to import.

Wolph
  • 78,177
  • 11
  • 137
  • 148
  • But again, I am wondering about the apparent conflict between DRY and separation of logic. It looks like this solution throws the latter out the window. That's fine if that's what you are OK with that, but is there a more peaceful way to reconcile? – jMyles Nov 19 '10 at 15:35
  • @Justin Myles Holmes: I use this solution because I don't think there's a clean way to do it with Django itself. You can hack around it by using the `with` statement together with the `include` statement. But that's just messy... as soon as you start doing something beyond the `extends` statement than you break all reusability. Like the Django admin for example where you can't change the way things are rendered without defining custom template tags. – Wolph Nov 20 '10 at 02:15