diff --git a/avatar/models.py b/avatar/models.py
index 02de5c9..2bc94ef 100644
--- a/avatar/models.py
+++ b/avatar/models.py
@@ -56,6 +56,25 @@ def find_extension(format):
format = 'jpg'
return format
+
+def get_primary_avatar(user, size=80):
+ if not isinstance(user, User):
+ try:
+ user = User.objects.get(username=user)
+ except User.DoesNotExist:
+ return AVATAR_DEFAULT_URL
+ avatars = user.avatar_set.order_by('-date_uploaded')
+ primary = avatars.filter(primary=True)
+ if primary.count() > 0:
+ avatar = primary[0]
+ elif avatars.count() > 0:
+ avatar = avatars[0]
+ else:
+ avatar = None
+ if avatar:
+ if not avatar.thumbnail_exists(size):
+ avatar.create_thumbnail(size)
+ return avatar
class Avatar(models.Model):
user = models.ForeignKey(User)
diff --git a/avatar/templatetags/avatar_tags.py b/avatar/templatetags/avatar_tags.py
index 217c6bf..b0928be 100644
--- a/avatar/templatetags/avatar_tags.py
+++ b/avatar/templatetags/avatar_tags.py
@@ -4,28 +4,17 @@ from django import template
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.utils.hashcompat import md5_constructor
+from django.core.urlresolvers import reverse
-from avatar import AVATAR_DEFAULT_URL, AVATAR_GRAVATAR_BACKUP, AVATAR_GRAVATAR_DEFAULT
+from avatar.models import get_primary_avatar
+from avatar import AVATAR_DEFAULT_URL, AVATAR_GRAVATAR_BACKUP
+from avatar import AVATAR_GRAVATAR_DEFAULT
register = template.Library()
def avatar_url(user, size=80):
- if not isinstance(user, User):
- try:
- user = User.objects.get(username=user)
- except User.DoesNotExist:
- return AVATAR_DEFAULT_URL
- avatars = user.avatar_set.order_by('-date_uploaded')
- primary = avatars.filter(primary=True)
- if primary.count() > 0:
- avatar = primary[0]
- elif avatars.count() > 0:
- avatar = avatars[0]
- else:
- avatar = None
- if avatar is not None:
- if not avatar.thumbnail_exists(size):
- avatar.create_thumbnail(size)
+ avatar = get_primary_avatar(user, size=size)
+ if avatar:
return avatar.avatar_url(size)
else:
if AVATAR_GRAVATAR_BACKUP:
@@ -55,6 +44,19 @@ def avatar(user, size=80):
size, size)
register.simple_tag(avatar)
+def primary_avatar(user, size=80):
+ """
+ This tag tries to get the default avatar for a user without doing any db
+ requests. It achieve this by linking to a special view that will do all the
+ work for us. If that special view is then cached by a CDN for instance,
+ we will avoid many db calls.
+ """
+ alt = unicode(user)
+ url = reverse('avatar_render_primary', kwargs={'user' : user, 'size' : size})
+ return """
""" % (url, alt,
+ size, size)
+register.simple_tag(primary_avatar)
+
def render_avatar(avatar, size=80):
if not avatar.thumbnail_exists(size):
avatar.create_thumbnail(size)
diff --git a/avatar/urls.py b/avatar/urls.py
index c3dc07b..0ddc942 100644
--- a/avatar/urls.py
+++ b/avatar/urls.py
@@ -4,4 +4,5 @@ urlpatterns = patterns('avatar.views',
url('^add/$', 'add', name='avatar_add'),
url('^change/$', 'change', name='avatar_change'),
url('^delete/$', 'delete', name='avatar_delete'),
+ url('^render_primary/(?P[\+\w]+)/(?P[\d]+)/$', 'render_primary', name='avatar_render_primary'),
)
diff --git a/avatar/views.py b/avatar/views.py
index e909052..5b78e25 100644
--- a/avatar/views.py
+++ b/avatar/views.py
@@ -1,8 +1,8 @@
import os.path
-from avatar.models import Avatar, avatar_file_path
+from avatar.models import Avatar, avatar_file_path, get_primary_avatar
from avatar.forms import PrimaryAvatarForm, DeleteAvatarForm, UploadAvatarForm
-from django.http import HttpResponseRedirect
+from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth.decorators import login_required
@@ -64,7 +64,7 @@ def _get_avatars(user):
else:
# Slice the default set now that we used the queryset for the primary avatar
avatars = avatars[:AVATAR_MAX_AVATARS_PER_USER]
- return (avatar, avatars)
+ return (avatar, avatars)
@login_required
def add(request, extra_context={}, next_override=None):
@@ -164,3 +164,16 @@ def delete(request, extra_context={}, next_override=None):
'next': next_override or _get_next(request), }
)
)
+
+def render_primary(request, user=None, size=80, extra_context={}):
+ avatar = get_primary_avatar(user, size=size)
+ if avatar:
+ # FIXME: later, add an option to render the resized avatar dynamically
+ # instead of redirecting to an already created static file. This could
+ # be useful in certain situations, particulary if there is a CDN and
+ # we want to minimize the storage usage on our static server, letting
+ # the CDN store those files instead
+ return HttpResponseRedirect(avatar.avatar_url(size))
+ else:
+ return HttpResponseRedirect(AVATAR_DEFAULT_URL)
+