I’m planning to cover all of what Django can do, but for now, let’s start simple with something most Django developers spend way too much time creating: Custom tags.
Django’s nice enough to provide a @register.simple_tag decorator for creating very basic tags that don’t take a context but do take parameters. This is great, but what if you want more? Many Django applications use the same boilerplate time and time again to create their tags, but we make it much easier.
Introducing @basictag and @blocktag.
@basictag
Ever wanted to use Django’s @register.simple_tag but needed access to the context? I’ve found far too many cases where this would be useful, but Django doesn’t make this easy. Your tag code would end up looking like this:
class MyTagNode(template.Node): def __init__(self, arg1, arg2): self.arg1 = arg1 self.arg2 = arg2 def render(self, context): arg1 = Variable(self.arg1).resolve(context) arg2 = Variable(self.arg2).resolve(context) return context['user'] @register.tag def mytag(parser, token): bits = token.split_contents() return MyTagNode(bits[1], bits[2])
Do this a few times and it’s bound to drive you nuts. How about this instead?
from djblets.util.decorators import basictag @register.tag @basictag(takes_context=True) def mytag(context, arg1, arg2): return context['user']
Far less code and increased readability. Hooray!
@blocktag
@blocktag aims to do the same thing @basictag does but for block tags. A block tag is a tag that contains nested content, like @spaceless or @for. This usually requires even more boilerplate than the above code fragment, except with the added complexity of having to grab the contents of the block.
We’ve condensed it down to this:
from djblets.util.decorators import blocktag @register.tag @blocktag def blinkblock(context, nodelist, arg1, arg2): return "<blink>%s</blink>" % nodelist.render(context)
If you’ve built block tags in the past, you’ll appreciate how simple that was.
Pretty nice work.
I suppose these could find their way into django trunk at some point.
Hi, There’s also this undocumented ferutae that would help you achieve the same thing with a little less effort ! If the plugin’s model has a render_template’ field,the plugin will use that value when calling render. Here’s an example model : class PagePreviewList(CMSPlugin): render_template = models.CharField(_( template’), max_length=100, choices=PLUGIN_TEMPLATES)So this way you get a select widget in the plugin’s admin view, and you don’t need to tweak with the instance’s properties in the render function. It would be nice if that ferutae would be documented We found out about while looking at the django-cms source.Please let me know if it works out for you too !