Usage¶
A simple example¶
A very basic tag which takes no arguments and always returns 'hello world'
would be:
from classytags.core import Tag
from django import template
register = template.Library()
class HelloWorld(Tag):
name = 'hello_world'
def render_tag(self, context):
return 'hello world'
register.tag(HelloWorld)
Now let’s explain this. To create a tag, you subclass classytags.core.Tag
and define a classytags.core.Tag.render_tag()
method which takes the
context and any template tag options you define as arguments to the method.
Since we did not define any options for this tag, it only takes context. The
classytags.core.Tag.render_tag()
method should always return a string.
classytags.core.Tag.render_tag
on a tag class is what is used when
registering the tag with a Django template tag library and also what will be
used in the template.
Defining options¶
Defining options is done by setting the classytags.core.Tag.options
attribute on your tag class to an instance of classytags.core.Options
.
The Options
class takes any amount of argument objects or strings (called
breakpoints) as initialization arguments.
Let’s build a tag which takes a single argument and an optional ‘as varname’ argument:
from classytags.core import Tag, Options
from classytags.arguments import Argument
from django import template
register = template.Library()
class Hello(Tag):
name = 'hello'
options = Options(
Argument('name'),
'as',
Argument('varname', required=False, resolve=False)
)
def render_tag(self, context, name, varname):
output = 'hello %s' % name
if varname:
context[varname] = output
return ''
else:
return output
register.tag(Hello)
In a template we could now do either {% hello "world" %}
which would output
'hello world'
or {% hello "world" as "varname" %}
which would output
nothing but set the {{ varname }}
template variable to 'hello world'
.
You may also use {% hello "world" as varname %}
to achieve the same result
like the last example.
Writing a block tag¶
You can write tags which wrap a block (nodelist) in the template. An example for
this kind of tag is Django’s built-in {% with %}
tag.
To write the {% with %}
tag from Django using django-classy-tags you would
do:
from classytags.core import Tag, Options
from classytags.arguments import Argument
from django import template
register = template.Library()
class With(Tag):
name = 'with'
options = Options(
Argument('variable'),
'as',
Argument('varname', resolve=False),
blocks=[('endwith', 'nodelist')],
)
def render_tag(self, context, variable, varname, nodelist):
context.push()
context[varname] = variable
output = nodelist.render(context)
context.pop()
return output
register.tag(With)
Working with multiple blocks¶
If you’re working with multiple, optional blocks, the nodelist is always credited to the leftmost block name.
For example the Django for
tag accepts an optional empty
block. Let’s
take following classytag options:
options = Options(
CommaSeperatableMultiValueArgument('loopvars'),
'in',
arguments.Argument('values'),
blocks=[('empty', 'pre_empty'), ('endfor', 'post_empty')],
)
If you use it with {% for x in y %}hello{% empty %}world{% enfor %}
the
pre_empty argument to your classytags.arguments.Argument.render_tag`()
would hold a nodelist containing hello
, post_empty would contain
world
. Now if you have {% for x in y%}{{ hello }}{% endfor %}
,
pre_empty remains the same, but post_empty is an empty nodelist.
Advanced Block Definition¶
Sometimes you might want to allow your blocktag to be terminated by a variable
end tag to make templates more readable. This is for example done in the
block
tag in Django, where you can do
{% block myblock %}...{% endblock %}
as well as
{% block myblock %}...{% endblock myblock %}
. To do so in classytags, you
have to use advanced block definitions using the
classytags.blocks.BlockDefinition
class together with the
classytags.blocks.VariableBlockName
class.
An example for a tag with the same signature as Django’s block tag:
class Block(Tag):
options = Options(
Argument('name', resolve=False),
blocks=[
BlockDefinition('nodelist', VariableBlockName('endblock %(value)s', 'name'), 'endblock')
]
)