You can extend django-classy-tags by writing your own subclasses of classytags.arguments.Argument which behave to your needs. If that does not cover your needs, you may also subclass classytags.core.Options and set a custom argument parser, which should subclass classytags.parser.Parser.
The most important method in this class for customization is classytags.arguments.Argument.parse(), so let’s have a closer look at it. It takes exactly four arguments, which are as follows:
The parse method must return a boolean value:
So let’s look at the standard classytags.arguments.Argument.parse():
def parse(self, parser, token, tagname, kwargs):
"""
Parse a token.
"""
if self.name in kwargs:
return False
else:
kwargs[self.name] = self.parse_token(parser, token)
return True
First it checks if the name is already in kwargs. If so, return False and let the next argument handle this token. Otherwise do some checking if we should resolve this token or not and add it to kwargs. Finally return True.
You might notice the classytags.arguments.Argument.parse_token() method used there. This method is responsible for turning an token into a template variable, a filter expression or any other object which allows to be resolved against a context. The one in classytags.arguments.Argument looks like this:
def parse_token(self, parser, token):
if self.no_resolve:
return TemplateConstant(token)
else:
return parser.compile_filter(token)
If all you want to do is clean arguments or enforce a certain type, you can just change the classytags.arguments.Argument.value_class of your subclass of classytags.arguments.Argument to a subclass of classytags.values.StringValue which implements a clean method in which you can check the type and/or cast a type on the value. For further information on value classes, see classytags.values.
The argument parser was written with extensibility in mind. All important steps are split into individual methods which can be overwritten. For information about those methods, please refer to the reference about classytags.parser.Parser.
To use a custom parser, provide it as the parser_class keyword argument to classytags.core.Options.
Note
Each time your tag gets parsed, a new instance of the parser class gets created. This makes it safe to use self.
Let’s make an argument which, when resolved, returns a template.
First we need a helper class which, after resolving loads the template specified by the value:
from django.template.loader import get_template
class TemplateResolver(object):
def __init__(self, real):
self.real = real
def resolve(self, context):
value = self.real.resolve(context)
return get_template(value)
Now for the real argument:
from classytags.arguments import Argument
class TemplateArgument(Argument):
def parse_token(self, parser, token):
real = super(TemplateArgument, self).parse_token(parser, token)
return TemplateResolver(real)