Skip to content

Commit

Permalink
S3 storage for avatars can be activated. Needs some documentation. Lo…
Browse files Browse the repository at this point in the history
…ok at the end of the settings.py file.

git-svn-id: http://django-profile.googlecode.com/svn/trunk/userprofile@408 7b2eb738-463f-0410-8820-43b14e3dcc91
  • Loading branch information
david.rubert committed May 14, 2009
1 parent 8a03f47 commit 638837d
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 23 deletions.
33 changes: 28 additions & 5 deletions models.py
Expand Up @@ -9,9 +9,19 @@
from django.core.mail import send_mail
from django.conf import settings
from userprofile.countries import CountryField
from django.core.files.storage import default_storage
if hasattr(settings, "AWS_SECRET_ACCESS_KEY"):
try:
from backends.S3Storage import S3Storage
storage = S3Storage()
except ImportError:
raise S3BackendNotFound
else:
storage = default_storage
import datetime
import cPickle as pickle
import base64
import urllib
import os.path
try:
from PIL import Image, ImageFilter
Expand Down Expand Up @@ -49,7 +59,7 @@ class Avatar(models.Model):
"""
Avatar model
"""
image = models.ImageField(upload_to="avatars/%Y/%b/%d")
image = models.ImageField(upload_to="avatars/%Y/%b/%d", storage=storage)
user = models.ForeignKey(User)
date = models.DateTimeField(auto_now_add=True)
valid = models.BooleanField()
Expand All @@ -61,23 +71,33 @@ def __unicode__(self):
return _("%s's Avatar") % self.user

def delete(self):
base, filename = os.path.split(self.image.path)
if hasattr(settings, "AWS_SECRET_ACCESS_KEY"):
path = urllib.unquote(self.image.name)
else:
path = self.image.path

base, filename = os.path.split(path)
name, extension = os.path.splitext(filename)
for key in AVATAR_SIZES:
try:
os.remove(os.path.join(base, "%s.%s%s" % (name, key, extension)))
storage.delete(os.path.join(base, "%s.%s%s" % (name, key, extension)))
except:
pass

super(Avatar, self).delete()

def save(self):
for avatar in Avatar.objects.filter(user=self.user, valid=self.valid).exclude(id=self.id):
base, filename = os.path.split(avatar.image.path)
if hasattr(settings, "AWS_SECRET_ACCESS_KEY"):
path = urllib.unquote(self.image.name)
else:
path = avatar.image.path

base, filename = os.path.split(path)
name, extension = os.path.splitext(filename)
for key in AVATAR_SIZES:
try:
os.remove(os.path.join(base, "%s.%s%s" % (name, key, extension)))
storage.delete(os.path.join(base, "%s.%s%s" % (name, key, extension)))
except:
pass
avatar.delete()
Expand Down Expand Up @@ -167,5 +187,8 @@ def resend(self):
class UserProfileMediaNotFound(Exception):
pass

class S3BackendNotFound(Exception):
pass

class GoogleDataAPINotFound(Exception):
pass
38 changes: 29 additions & 9 deletions templatetags/avatars.py
Expand Up @@ -2,8 +2,11 @@
from django.template import Library, Node, Template, TemplateSyntaxError, \
Variable
from django.utils.translation import ugettext as _
from userprofile.models import Avatar, AVATAR_SIZES
from userprofile.models import Avatar, AVATAR_SIZES, S3BackendNotFound
from django.contrib.auth.models import User
from django.core.files.base import ContentFile
import urllib
from cStringIO import StringIO
from django.conf import settings
try:
from PIL import Image
Expand All @@ -15,6 +18,15 @@
import os
import urlparse
import time
from django.core.files.storage import default_storage
if hasattr(settings, "AWS_SECRET_ACCESS_KEY"):
try:
from backends.S3Storage import S3Storage
storage = S3Storage()
except ImportError:
raise S3BackendNotFound
else:
storage = default_storage

register = Library()

Expand Down Expand Up @@ -46,26 +58,34 @@ def render(self, context):
try:
user = self.user.resolve(context)
avatar = Avatar.objects.get(user=user, valid=True).image
avatar_path = avatar.path
if not os.path.isfile(avatar_path):
if hasattr(settings, "AWS_SECRET_ACCESS_KEY"):
avatar_path = avatar.name
else:
avatar_path = avatar.path

if not storage.exists(avatar_path):
raise
base, filename = os.path.split(avatar_path)
name, extension = os.path.splitext(filename)
filename = os.path.join(base, "%s.%s%s" % (name, self.size, extension))
url_tuple = urlparse.urlparse(avatar.url)
url = urlparse.urljoin(url_tuple[2], "%s.%s%s" % (name, self.size, extension))
url = urlparse.urljoin(urllib.unquote(urlparse.urlunparse(url_tuple)), "%s.%s%s" % (name, self.size, extension))

if not storage.exists(filename):
thumb = Image.open(ContentFile(avatar.read()))
thumb.thumbnail((self.size, self.size), Image.ANTIALIAS)
f = StringIO()
thumb.save(f, "JPEG")
f.seek(0)
storage.save(filename, ContentFile(f.read()))

except:
avatar_path = DEFAULT_AVATAR
base, filename = os.path.split(avatar_path)
generic, extension = os.path.splitext(filename)
filename = os.path.join(base, "%s.%s%s" % (generic, self.size, extension))
url = filename.replace(settings.MEDIA_ROOT, settings.MEDIA_URL)

if not os.path.isfile(filename):
image = Image.open(avatar_path)
image.thumbnail((self.size, self.size), Image.ANTIALIAS)
image.save(filename, "JPEG")

return url

@register.tag('avatar')
Expand Down
36 changes: 27 additions & 9 deletions views.py
Expand Up @@ -15,8 +15,11 @@
from django.db import models
from django.contrib.auth.models import User, SiteProfileNotAvailable
from userprofile.models import EmailValidation, Avatar, UserProfileMediaNotFound, \
GoogleDataAPINotFound
GoogleDataAPINotFound, S3BackendNotFound
from django.template import RequestContext
from cStringIO import StringIO
from django.core.files.base import ContentFile
import urlparse
from django.conf import settings
from xml.dom import minidom
import urllib2
Expand All @@ -27,6 +30,9 @@
import os
from userprofile import signals

if hasattr(settings, "AWS_SECRET_ACCESS_KEY"):
from backends.S3Storage import S3Storage

if hasattr(settings, "AVATAR_QUOTA"):
from userprofile.uploadhandler import QuotaUploadHandler

Expand Down Expand Up @@ -226,11 +232,14 @@ def avatarchoose(request):
form = AvatarForm(request.POST, request.FILES)
if form.is_valid():
image = form.cleaned_data.get('url') or form.cleaned_data.get('photo')
avatar = Avatar(user=request.user, image=image, valid=False)
avatar.image.save("%s.jpg" % request.user.username, image)
image = Image.open(avatar.image.path)
image.thumbnail((480, 480), Image.ANTIALIAS)
image.convert("RGB").save(avatar.image.path, "JPEG")
thumb = Image.open(ContentFile(image.read()))
thumb.thumbnail((480, 480), Image.ANTIALIAS)
thumb.convert("RGB")
f = StringIO()
thumb.save(f, "JPEG")
f.seek(0)
avatar = Avatar(user=request.user, image="", valid=False)
avatar.image.save("%s.jpg" % request.user.username, ContentFile(f.read()))
avatar.save()

signal_responses = signals.post_signal.send(sender=avatarchoose, request=request, form=form)
Expand Down Expand Up @@ -262,7 +271,7 @@ def avatarcrop(request):
if not request.method == "POST":
form = AvatarCropForm()
else:
image = Image.open(avatar.image.path)
image = Image.open(ContentFile(avatar.image.read()))
form = AvatarCropForm(image, request.POST)
if form.is_valid():
top = int(form.cleaned_data.get('top'))
Expand All @@ -288,7 +297,15 @@ def avatarcrop(request):
if image.mode not in ('L', 'RGB'):
image = image.convert('RGB')

image.save(avatar.image.path)
if hasattr(settings, "AWS_SECRET_ACCESS_KEY"):
f = StringIO()
image.save(f, "JPEG")
f.seek(0)
avatar.image.delete()
avatar.image.save("%s.jpg" % request.user.username, ContentFile(f.read()))
else:
image.save(avatar.image.path)

avatar.valid = True
avatar.save()
request.user.message_set.create(message=_("Your new avatar has been saved successfully."))
Expand All @@ -305,7 +322,8 @@ def avatarcrop(request):
def avatardelete(request, avatar_id=False):
if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
try:
Avatar.objects.get(user=request.user, valid=True).delete()
for avatar in Avatar.objects.filter(user=request.user):
avatar.delete()
return HttpResponse(simplejson.dumps({'success': True}))
except:
return HttpResponse(simplejson.dumps({'success': False}))
Expand Down

0 comments on commit 638837d

Please sign in to comment.