Wiki

Clone wiki

django-sniplates / Home

Sniplate

What is it? Well, it's a way to keep collections of template snippets organised together. It works very much like {% include %}, but allows you to pull top-level blocks from other templates.

N.B. As of 1.0.2 you can reference blocks at _any_ level.

Getting started

1. Write a template called sniplate/first.snip

2. In there, put the following:

{% block simple %}
My first sniplate!
{% endblock %}

3. In another template on your site, add:

{% load sniplate %}
{% sniplate "first.snip" "simple" %}

It's as simple as that!

And that's it?

Well, not quite. Just like {% include %}, you can pass some extra parameters, much like {% with %}.

Add to your sniplate:

{% block welcome %}
Hello, {{ name }}
{% endblock %}

And then try:

{% sniplate "first.snip" "welcome" name="Bob" %}

{# or #}

{% sniplate "first" "welcome" name=auth.user.get_full_name %}

What about my other templates?

If you specify a sniplate library with a / in it, it will be used verbatim, instead of prepending "sniplate/" to it. So, you can re-use blocks in your other templates as well, so long as they're not within other blocks.

Forms

Now included is a Forms module to help with customised widgets. It's still a work in progress, but is already in service.

Tags

All of the tags can act like with/include, in that any extra keyword arguments will be pushed into the context before rendering.

{% form <form> <lib> [form=...] [key=val...] %}

This renders the specified form, using the supplied snippet lib. It will use the block named "form" to render. This can be overridden by passing form=.

{% field <field> [widget=...] [key=val...] %}

Inside the form rendering, you can specify to render a field. If widget isn't specified, the field will try to determine the widget to use by looking for:

  • FieldType__FieldName
  • FieldName
  • FieldType

So, for instance, if you have an IntegerField called "count", it would search:

  • IntegerField__count
  • count
  • IntegerField

If it can't be found, the block called "field" will be used.

{% use block [key=val key=val] %}

A helper function that will render the specified block in place of this one. It's basically {% include %} but for blocks.

Filters

There is also included one filter, though not directly related to forms.

{{ value|append:param }}

It will treat both values as strings, and yield the param appended to the value.

Example

Here's a very simple sample form template.

{% load form %}

{% block field %}
{% if not nolabel %}
<label for="{{ field.auto_id }}" {% if field.required %}class="required"{% endif %}> {{ label|default:field.label }} </label>
{% endif %}
<input type="{{ field_type|default:"text" }}" name="{{ field.html_name }}" id="{{ field.auto_id }}" value="{{ field.value|default:"" }}" {% if field.errors %}class="error"{% endif %} />
{{ field.help_text }}
{% endblock %}

# Override to use HTML5 email field
{% block EmailField %}{% use field type="email" %}{% endblock %}

{% block TypedChoiceField %}
{% if not nolabel %}
<label for="{{ field.id }}" {% if field.required %}class="required"{% endif %}> {{ field.label }} </label>
{% endif %}
<select name="{{ field.html_name }}" id="{{ field.auto_id }}" {% if field.errors %}class="error"{% endif %}>
  {% for option_value, option_label in field.field.choices %}
  <option value="{{ option_value }}" {% if field.value == option_value|safe %}selected="selected"{% endif %}>{{ option_label }}</option>
  {% endfor %}
</select>
{{ field.help_text }}
{% endblock %}

# How to render the actual form
{% block form %}
{% for field in form %}
<li>{% field field %}</li>
{% endfor %}
{% endblock %}

# Override the default for all fields called "address"
{% block address %}{% use "Textarea" nolabel=True %}{% endblock %}

Updated