get_now templatetag

On several occasions, I (and the templaters on my team) have needed a way to do datetime comparisons from within a template. The first example is testing if the pub_date on an object is today. Usually, I just end up writing a helper method on the model to do this; something like is_today. However, we've run into several instances where this wasn't possible or it would have just been too much of a mess to write these helper methods on every model. I then decided to create a little templatetag to take care of this for me.

The first idea was to just create a get_today tag that would return the name of today at a string. But thinking into further, I decided to make it so it'd return any form of datatime for today by accepting a format string. For instance, the following example would fetch what I wanted earlier; the name of today at a string.

{% get_now:"l" as var_name %}

This is obviously only the tip of what you can return. You can return any form of datetime.now() by just passing it a format string. A reference for this can be found here.

This all seems simple enough, but that's because it really is! I don't suppose there's any easier way to explain it than just to show the code.

from django.core import template
from django.utils.dateformat import format
import datetime
import re

register = template.Library()

### Templates Tags

class GetNow(template.Node):
    def __init__(self, format_string, var_name):
        self.format_string = format_string
        self.var_name = var_name

    def render(self, context):
        context[self.var_name] = format(datetime.datetime.now(), self.format_string)
        return ''
    
def get_now(parser, token):
    """
    Returns a string of now formated as specified.
    
    Syntax::
    
        {% get_now as [var_name] %}
        
    """
    r1 = re.compile('[\"|\'](.+)[\"|\']') # format string regex
    r2 = re.compile('as (.+)') # var_name regex
    
    format_string = r1.findall(token.contents)
    var_name = r2.findall(token.contents)
    bits = token.contents.split()
    
    if format_string and var_name:
        return GetNow(format_string[0], var_name[0])
    if not var_name:
        raise template.TemplateSyntaxError, "'%s' tag requires a variable name to be given" % bits[0]
    if not format_string:
        raise template.TemplateSyntaxError, "'%s' tag requires a format string like 'jS F Y H:i'" % bits[0]

register.tag(get_now)

The only thing special about this tag is that I decided to use regular expressions to pick apart the token instead of relying on the standard bit[n] technique. This was all because normally, the token consists of full words, but in this tag, we need to pull the format string which includes spaces.

The rest of the logic should all be pretty self explanatory. I'll leave you with that!

Cheers!

Posted by Sean Stoops on March 8, 2008

datetime, django, python, regex, template, templatetag


Comments

No one has said anything yet...

Post a Comment

(not displayed)

Comment:

The SigB Links:

External Links:

Archives

RSS feeds

A Django project.
Made with vim