Creating a Django Gravatar Template Tag (Part 1)

I spent the last couple of days implementing Django's comment framework for my blog. Since making a comment requires the user's e-mail address, I wanted to display the user's gravatar icon next to their name (but only if they have a gravatar setup).

How Gravatar Works

Gravatar

Gravatar is a free service that lets a user associate a graphic with their e-mail address. The only thing required for sites to implement the service is to create a md5 hash of the user's e-mail address. You then make a request to retrieve that user's icon:

http://gravatar.com/avatar/?gravatar_id=1440826ae9908cf7c415dbfd3a66b240&s=64

Lance McNearney

The above request returns my gravatar icon at 64x64 pixels (the little graphic to the left).

Existing Django/Python Implementations

Searching for existing implementations of Gravatar template tags turned up the following two results:

The first project is aimed at extending Django's User model. It also renders the gravatar as an img tag without providing any context variables for me to integrate into my own template HTML.

The blog post by Drew Engelson was a much better implementation. The only piece missing was that I wanted to check to see if a gravatar exists for an e-mail address instead of just providing a default image.

Since neither one of these solutions supported checking if a gravatar exists, I set out to create my own template tag.

Does a Gravatar Exist?

The gravatar service will return its own "default" image for users who don't have a gravatar setup. You can also pass a "default" parameter to the service with your request and it will issue a 302 re-direct to that address instead of returning the service's default image.

My goal was to issue a simple HEAD request to the service with a default parameter and if it issued a 302 re-direct response I knew the gravatar didn't exist for the specified e-mail address. Unfortunately, the urllib library in Python doesn't support HEAD requests and it also automatically follows re-directs to the new address (and doesn't tell you that it followed the re-direct). Because of this, I needed to use the lower level httplib library.

Here's a simple test script that implements the functionality I wanted to achieve:

#!/usr/bin/env python
import sys
import urllib, hashlib, httplib

GRAVATAR_DOMAIN = 'gravatar.com'
GRAVATAR_PATH = '/avatar/'

def main():
    email = sys.argv[1]
    hash = hashlib.md5(email).hexdigest()
    print email + ' = ' + hash

    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)
    print full_path

    # Create connection and test for 302 redirect
    conn = httplib.HTTPConnection(GRAVATAR_DOMAIN)
    conn.request('HEAD', full_path)
    response = conn.getresponse()
    print response.status

    if response.status == 302:
        print 'No gravatar :('
    else:
        print 'Gravatar found :)'

if __name__ == '__main__':
    main()

You can download the full gravatar test script if you're interested.

With my e-mail address passed to the script it found a valid gravatar:

$ gravatar.py lance@mcnearney.net
lance@mcnearney.net = 1440826ae9908cf7c415dbfd3a66b240
/avatar/?default=%2F&s=1&gravatar_id=1440826ae9908cf7c415dbfd3a66b240
200
Gravatar found :)

And testing with a bogus e-mail address returned the following:

$ gravatar.py bogus@example.com
bogus@example.com = 42d33ed1a79b32726b43ade0460c7ff8
/avatar/?default=%2F&s=1&gravatar_id=42d33ed1a79b32726b43ade0460c7ff8
302
No gravatar :(

Now I just needed to turn this example code into a Django template tag...

Read part two of this post for the template tag implementation.

Categories: Django, Python

1 Comment

Hey Lance,

I'm glad you found my Gravatar post helpful. Nice addition!

Drew Engelson Drew Engelson
April 21, 2010