TTag reference

Overview

TTag replaces the normal method of creating custom template tags. It uses a custom template Node subclass called Tag which handles all of the relevant aspects of a tag: defining and parsing arguments, handling validation, resolving variables from the context, and rendering output.

Tag

class ttag.Tag

A representation of a template tag. For example:

class Welcome(ttag.Tag):

    def output(self, data):
        return "Hi there!"

Meta options

A Tag can take options via a Meta inner class:

class Welcome(ttag.Tag):

    class Meta:
        name = "hi"
ttag.Tag.Meta.name
Explicitly choose a name for the tag. If not given, the tag’s name will be
created by taking the class’s name and converting it from CamelCase to under_score format. For example, AmazingStuff would turn into {% amazing_stuff %}.
ttag.Tag.Meta.register

Register the tag in a tag library.

Alternatively, a tag can still be rendered the standard way: some_library.tag(ThisTag).

ttag.Tag.Meta.block

Retrieve subsequent template nodes until {% end[tagname] %}, adding them to self.nodelists.

output

If your tag does not modify the output, override this method to change the output of this tag.

.output(self, data)
Parameters:
  • data – A dictionary of data built from the arguments this tag uses, usually built by the resolve() method.

render

As an alternative to overriding the output method, a TemplateTag subclass may directly override the render method. This is useful for when you want to alter the context.

.render(self, context)
param context:The current template context.

render must return a unicode string.

If your tag doesn’t return anything (e.g., it only manipulates the context), render should simply return an empty string.

To retrieve the values of the tag’s arguments, if any, use the following method inside render:

.. method:: .resolve(self, context)

Retrieve the values of the tag’s arguments.

param context:The current template context.
returns:A data dictionary containing the values of the tag’s arguments.

Arguments

Arguments can be either positional or named. They are specified as properties of the tag class, in a similar way to Django’s forms and models.

If the property name clashes with a append a trailing slash - it will be removed from the argument’s name. For example, pay attention to the as_ argument in the tag below:

class SetTag(ttag.Tag):
    value = ttag.Arg(positional=True)
    as_ = ttag.BasicArg()

    def render(self, context):
        data = self.resolve(context)
        as_var = data['as']
        context[as_var] = data['value']
        return ''

Positional arguments

An argument may be marked as positional by using the positional flag:

class PositionalTag(ttag.Tag):
    first = ttag.Arg(positional=True)
    second = ttag.Arg(positional=True)

This would result in a tag named positional which took two required arguments, which would be assigned to 'first' and 'second' items of the data dictionary returned by the resolve method.

Use the ConstantArg for simple required string-based arguments which assist readability (this Arg assumes positional=True):

class MeasureTag(ttag.Tag):
    start = ttag.Arg(positional=True)
    to = ttag.ConstantArg()
    finish = ttag.Arg(positional=True)

Named arguments

Named arguments can appear in any order in a tag’s arguments, after the positional arguments. They are specified as follows:

class NamedTag(ttag.Tag):
    limit = ttag.Arg(required=False)
    offset = ttag.Arg(required=False)

This would create a tag named named which took two optional arguments, limit and offset. They could be specified in any order:

{% named %}

{% named limit 10 %}

{% named offset 25 %}

{% named limit 15 offset 42 %}

{% named offset 4 limit 12 %}

If you prefer “keyword” style named arguments (e.g. {% named offset=25 %}, you can use the ``keyword parameter:

class NamedTag(ttag.Tag):
    limit = ttag.Arg(required=False, keyword=True)
    offset = ttag.Arg(required=False, keyword=True)

If an optional argument is not specified in the template, it will not be added to the data dictionary. Alternately, use default to have a default value added to the data dictionary if an argument is not provided:

class NamedTag(ttag.Tag):
    limit = ttag.Arg(default=100)
    offset = ttag.Arg(required=False)

Argument Types

Arg and its subclasses provide various other levels of parsing and validation.

Arg

This is the base class for all other argument types. Behavior can be defined via the following constructor arguments.

required

Whether the argument is required as part of the tag definition in the template. Required positional arguments can not occur after optional ones.

Defaults to True.

default

The default value for this argument if it is not specified.

If None and the field is required, an exception will be raised when the template is parsed.

Defaults to None.

null

Determines whether a value of None is an acceptable value for the argument resolution.

When set to False, a value of None or a missing context variable will cause a TemplateTagValidationError when this argument is cleaned.

Defaults to False.

positional

Whether this is a positional tag (i.e. the argument name is not part of the tag definition).

Defaults to False.

keyword

Use an equals to separate the value from the argument name, rather than the standard space separation.

This parameter is only used for named arguments (i.e. positional=False).

Defaults to False.

BasicArg

A simpler argument which doesn’t compile its value as a FilterExpression.

Example usage:

class GetUsers(ttag.Tag)
    as_ = ttag.BasicArg()

    def render(self, context)
        data = self.resolve(data)
        context[data['as']] = Users.objects.all()
        return ''

IntegerArg

Validates that the argument is an integer, otherwise throws a template error.

StringArg

Validates that the argument is a string instance, otherwise throws a template error.

BooleanArg

A “flag” argument which doesn’t consume any additional tokens.

If it is not defined in the tag, the argument value will not exist in the resolved data dictionary.

For example:

class CoolTag(ttag.Tag)
    cool = ttag.BooleanArg()

    def output(self, data):
        if 'cool' in data:
            return "That's cool!"
        else:
            return "Uncool."

IsInstanceArg

Validates that the argument is an instance of the provided class (cls), otherwise throws a a template error, using the cls_name in the error message.

date = IsInstanceArg(cls=datetime.date, cls_name=_(‘Date’))

DateTimeArg

Validates that the argument is a datetime instance, otherwise throws a template error.

DateArg

Validates that the argument is a date instance, otherwise throws a template error.

TimeArg

Validates that the argument is a time instance, otherwise throws a template error.

ModelInstanceArg

Validates that the passed in value is an instance of the specified Model class. It takes a single additional named argument, model.

model

The Model class you want to validate against.

KeywordsArg

Parses one or more additional tokens as keywords.

Use compact and verbose boolean parameters to control the keyword argument format. The default format is compact:

{% compact with foo=1 bar=2 %}

Setting verbose=True and compact=False will require verbose format:

{% verbose with 1 as foo and 2 as bar %}

If verbose=True and compact is left as True, then either (or even both) formats are allowed. This is usually only used for backwards compatibility:

{% mixed with foo=1 bar=2 %}
{% mixed with 1 as foo and 2 as bar %}
{% mixed with foo=1 and 2 as bar %}

In verbose mode, the and is required for multiple arguments, in mixed mode it is optional, and in compact mode it is obviously not used.

Use the compile_values parameter to compile keyword values as template variables (defaults to True).

Full Example

This example provides a template tag which outputs a tweaked version of the instance name passed in. It demonstrates using the various Arg types:

class TweakName(ttag.Tag):
    """
    Provides the tweak_name template tag, which outputs a
    slightly modified version of the NamedModel instance passed in.

    {% tweak_name instance [offset=0] [limit=10] [reverse] %}
    """
            instance = ttag.ModelInstanceArg(positional=True, model=NamedModel))
    offset = ttag.IntegerArg(default=0, keyword=True)
    limit = ttag.IntegerArg(default=10, keyword=True)
    reverse = ttag.BooleanArg()

    def output(self, data):
        name = data['instance'].name

        # reverse if appropriate
        if 'reverse' in data:
            name = name[::-1]

        # check that limit is not < 0
        if data['limit'] < 0:
            raise ttag.TagValidationError("limit must be >= 0")

        # apply our offset and limit
        name = name[data['offset']:data['limit']]

        # return the tweaked name
        return name

Example usages:

{% tweak_name obj limit=5 %}

{% tweak_name obj offset=1 %}

{% tweak_name obj reverse %}

{% tweak_name obj offset=1 limit=5 reverse %}