Update (January 31, 2011) I just released django-simplegravatar, a pluggable Django template tag based heavily on this post.
This blog is written in Python on Django* and utilizes basic.remarks instead of FreeComment for the comments engine. To add some personalization to the comments, I thought avatars would be a nice touch and decided to implement Gravatar, a fantastic system for centrally managing one's avatar across multiple sites. Gravatar basically associates an image with an e-mail address. Here's mine:
The general idea is to recognize a commenter's e-mail address and automatically display their Gravatar (if they have one). Many web applications have Gravatar plugins such as Wordpress, Joomla, MovableType, etc. I came across a Django project called django-gravatar which attempts to provide this functionality, but since it relies on a User object, commenters would have to create a User account. In general, most commenters are not authenticated and would not have a User object in Django. Clearly, django-gravatar is not for us. No matter... implementing Gravatar couldn't be more simple.
All that is required to display a user's Gravatar is their e-mail address. The URL to the Gravatar image simply takes a hashed e-mail address to identify the user, and a few other optional parameters to control the size and what to do if there us no Gravatar associated with their e-mail address. Here's how to create a custom template tag to make this easy.
First, we need to create the template tag Python code. In a file called myproject/templatetags/mytags.py, the following logic creates a flexible custom tag.
import urllib, hashlib
from django import template
register = template.Library()
@register.inclusion_tag('templatetags/gravatar.html')
def show_gravatar(email, size=48):
default = "http://www.mysite.com/media/images/no-avatar.gif"
url = "http://www.gravatar.com/avatar.php?"
url += urllib.urlencode({
'gravatar_id': hashlib.md5(email).hexdigest(),
'default': default,
'size': str(size)
})
return {'gravatar': {'url': url, 'size': size}}
Notice that the e-mail address gets md5 encoded, and that the whole querystring is url encoded. Passing in the size parameter enables this tag to be used for Gravatars of varying sizes. The default URL specifies what to display if the commenter does not have a Gravatar.
Next, we need to create the template that defines the HTML output for the Gravatar image. In my case, myproject/templates/templatetags/gravatar.html.
<div class="gravatar">
<img src="{{ gravatar.url }}"
width="{{ gravatar.size }}"
height="{{ gravatar.size }}" border="0" /></div>
Got it? Pretty simple, huh?
Finally, we need to insert this custom tag into your template where the Gravatar should display. In my case, this is the post_detail.html template that controls my individual post page and comments. Here's the code snippit:
{% load mytags %}
{% if remark_list %}
<div id="comments">
<a name="comments"></a>
<h3>{{ remark_list|length }} comment{{ remark_list|pluralize }}</h3>
{% for remark in remark_list %}
<div class="comment">
{% show_gravatar remark.person_email 48 %}
<div class="comment_header">
{{ remark.person_name }} says...
</div>
<div class="comment_body">
{{ remark.remark|urlizetrunc:"60" }}
</div>
<div class="comment_footer">
Posted {{ remark.submit_date|date:"F j, Y, P" }}
</div>
</div>
{% endfor %}
</div>
{% endif %}
There are two significant pieces of this code:
- "{% load mytags %}" makes the custom template available to this template. Remember we called the file mytags.py?
- "{% show_gravatar remark.person_email 48 %}" instantiates the tag and passes the commenter's e-mail address and the desired Gravatar image size.
You can use CSS to style this up to your heart's desire. Keep in mind that you will always get a result back from Gravatar even if the commenter does not have a Gravatar. We specified a default image for these cases. If no default was specified, Gravatar will return its own default image (a blue Gravatar logo).
We could extend this to support the remaining Gravatar options, such as ratings, but I'll leave that up to you.
* In case you missed it, this is sarcastic reference to Ruby on Rails.
UPDATE (5/11/2010): The first paragraph of this article no longer accurately describes this blog's software architecture. It no longer uses basic.remarks, but was converted to Django Mingus and uses Disqus for comments (which has built-in Gravatar support).