Adding Gravatars

Wouldn’t it be cool if we could show user avatars next to comments? Let’s use the free Gravatar service for this. As usual, we’ll start with a test.

According to the Gravatar documentation a Gravatar profile image can be requested like this:

Where HASH is an MD5 hash of the user’s email address. We can use the hashlib package in the Python standard library to generate an MD5 hash.

Tip

There are lots of options for displaying gravatars such as setting the display size for the image and having a default image if there is no Gravatar for a specific email.

First, let’s write a test for Gravatars. This test will be added to our already existing test CommentModelTest since the plan is to add a method to the Comment model to get the Gravatar URL.

def test_gravatar_url(self):
    comment = Comment(body="My comment body", email="email@example.com")
    expected = "http://www.gravatar.com/avatar/5658ffccee7f0ebfda2b226238b1eb6e"
    self.assertEqual(comment.gravatar_url(), expected)

Note

We didn’t calculate that MD5 hashes in our head. You can use Python’s hashlib library to calculate the hash or just type md5 email@example.com into Duck Duck Go.

When running our tests now, we’ll see an error since we have not yet written a gravatar_url() method to the Comment model:

$ python manage.py test blog
Creating test database for alias 'default'...
....E.....................
======================================================================
ERROR: test_gravatar_url (blog.tests.CommentModelTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  ...
AttributeError: 'Comment' object has no attribute 'gravatar_url'

----------------------------------------------------------------------
Ran 26 tests in 0.175s

FAILED (errors=1)
Destroying test database for alias 'default'...

Adding comment gravatars

Let’s add a gravatar_url() method to Comment so our tests pass. This involves editing models.py:

def gravatar_url(self):
    # Get the md5 hash of the email address
    md5 = hashlib.md5(self.email.encode())
    digest = md5.hexdigest()

    return 'http://www.gravatar.com/avatar/{}'.format(digest)

Note

Remember to import the hashlib library at the top of our models.py file.

Tip

If you’ve never used hashlib before, this may look a little daunting. MD5 is a cryptographic hash function that takes a string of any size and creates a 128-bit binary string. When rendered as hexidecimal, it is a 32 character string.

self.email is always converted to unicode because it is possible that it is None since it is not required. If you’re feeling up to it, write a test for this case and see what happens.

If you run the tests at this point, you should see that our test case passes.

Displaying gravatars on the site

Now, let’s display the Gravatars with the comments.

In our content block in templates/blog/entry_detail.html, let’s add the Gravatar images:

{% for comment in entry.comment_set.all %}
    <p>
        <em>Posted by {{ comment.name }}</em>
        <img src="{{ comment.gravatar_url }}" align="left">
    </p>
    {{ comment|linebreaks }}
{% empty %}
    No comments yet.
{% endfor %}

If you fire up the development web server and look at a specific blog entry, you should see an image for each comment.