Creating a Django Gravatar Template Tag (Part 2)
This post is a continuation of the first post on creating a gravatar template tag.
My test script was fairly straight forward to get working as a template tag. The only gotcha was not realizing that any values passed into the template tag are simple strings and that it was my job to resolve any variables being passed in. Here's an example:
Template:
{% gravatar comment.user_email 64 as gravatar %}
Tag code:
class GravatarNode(Node): def __init__(self, email, size, varname): self.email = email def render(self, context): return self.email @register.tag def gravatar(parser, token): bits = token.contents.split() return GravatarNode(bits[1], bits[2], bits[4])
This template tag will render:
comment.user_email
Since I was hashing this value and passing it to the gravatar service it took me a little while to figure out what was happening.
To get it to resolve the actual value of the comment.user_email variable, you have to wrap the string variable in a template.Variable() and then call the resolve(context) method of the variable inside the tag's render() method:
class GravatarNode(Node): def __init__(self, email, size, varname): self.email = template.Variable(email) def render(self, context): return self.email.resolve(context) @register.tag def gravatar(parser, token): bits = token.contents.split() return GravatarNode(bits[1], bits[2], bits[4])
Now it will return the comment user's e-mail address.
Here's the completed code for the template tag. You can see how it's used in a template based on the main tag's comments:
from django import template from django.template import Library, Node, TemplateSyntaxError import urllib, hashlib, httplib register = Library() GRAVATAR_DOMAIN = 'gravatar.com' GRAVATAR_PATH = '/avatar/' class GravatarNode(Node): def __init__(self, email, size, varname): self.email = template.Variable(email) self.size = int(size) self.varname = varname def render(self, context): hash = hashlib.md5(self.email.resolve(context)).hexdigest() context[self.varname] = get_gravatar(hash, self.size) return '' def is_default(hash): ''' Returns whether the specified gravatar is returning the default icon. ''' try: query = urllib.urlencode({ 'gravatar_id': hash, 's': 1, # Smallest size available 'default': '/' # Causes a re-direct when the gravatar is missing }) full_path = '%s?%s' % (GRAVATAR_PATH, query) # Create connection and test for 302 redirect conn = httplib.HTTPConnection(GRAVATAR_DOMAIN) conn.request('HEAD', full_path) response = conn.getresponse() return response.status == 302 except: return True def get_gravatar(hash, size): ''' Returns an object with the gravatar information. ''' query = urllib.urlencode({ 'gravatar_id': hash, 's': size }) return { 'src': 'http://%s%s?%s' % (GRAVATAR_DOMAIN, GRAVATAR_PATH, query), 'width': size, 'height': size, 'is_default': is_default(hash) } @register.tag def gravatar(parser, token): ''' This tag is used for rendering a gravatar icon. You can also check that the gravatar exists by checking the is_default property. Usage:: {% gravatar email_address size as variable_name %} Example:: {% gravatar user.email 64 as icon %} {% if not icon.is_default %} <img src="{{ icon.src }}" width="{{ icon.width }}" height="{{ icon.height}}" alt=""/> {% endif %} ''' bits = token.contents.split() if len(bits) != 5: raise TemplateSyntaxError, 'gravatar takes exactly four arguments' if bits[3] != 'as': raise TemplateSyntaxError, 'third argument must be "as"' return GravatarNode(bits[1], bits[2], bits[4])
You can download full template tag here. Since I'm still fairly new to Django and Python I would appreciate any feedback anyone has to offer. Please add a comment or contact me directly. Thanks and enjoy!

Add Comment
Please fill out the form below to add a comment.
Comments are moderated and must be approved before they will appear on the site.