1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-07-16 08:16:55 +00:00

Make basic avatar operations work.

This commit is contained in:
xiez 2012-05-24 20:19:14 +08:00
parent 3308325e9a
commit 4c20e49613
18 changed files with 203 additions and 107 deletions

View File

@ -22,7 +22,8 @@ class UploadAvatarForm(forms.Form):
avatar = forms.ImageField()
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
# self.user = kwargs.pop('user')
self.emailuser = kwargs.pop('user').email
super(UploadAvatarForm, self).__init__(*args, **kwargs)
def clean_avatar(self):
@ -37,7 +38,7 @@ class UploadAvatarForm(forms.Form):
raise forms.ValidationError(
_(u"Your file is too big (%(size)s), the maximum allowed size is %(max_valid_size)s") %
{ 'size' : filesizeformat(data.size), 'max_valid_size' : filesizeformat(AVATAR_MAX_SIZE)} )
count = Avatar.objects.filter(user=self.user).count()
count = Avatar.objects.filter(emailuser=self.emailuser).count()
if AVATAR_MAX_AVATARS_PER_USER > 1 and \
count >= AVATAR_MAX_AVATARS_PER_USER:
raise forms.ValidationError(

4
avatar/i18n.sh.template Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
django-admin.py makemessages -l zh_CN -e py,html
django-admin.py compilemessages

Binary file not shown.

View File

@ -0,0 +1,101 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-05-24 11:16+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: forms.py:35
#, python-format
msgid ""
"%(ext)s is an invalid file extension. Authorized extensions are : "
"%(valid_exts_list)s"
msgstr ""
#: forms.py:39
#, python-format
msgid ""
"Your file is too big (%(size)s), the maximum allowed size is "
"%(max_valid_size)s"
msgstr "您的文件过大(%(size)s允许最大文件为 %(max_valid_size)s"
#: forms.py:45
#, python-format
msgid ""
"You already have %(nb_avatars)d avatars, and the maximum allowed is "
"%(nb_max_avatars)d."
msgstr ""
#: forms.py:57
msgid "choice"
msgstr "从已有头像中选择"
#: forms.py:68
msgid "choices"
msgstr "从已有头像中选择"
#: models.py:79
#, python-format
msgid "Avatar for %s"
msgstr ""
#: templates/avatar/add.html:5 templates/avatar/change.html:6
msgid "Your current avatar: "
msgstr "当前头像:"
#: templates/avatar/add.html:8 templates/avatar/change.html:9
msgid "You haven't uploaded an avatar yet. Please upload one now."
msgstr "您还没有上传自己的头像。请上传。"
#: templates/avatar/add.html:12 templates/avatar/change.html:20
msgid "Upload New Image"
msgstr "提交"
#: templates/avatar/change.html:15
msgid "Choose new Default"
msgstr "确定"
#: templates/avatar/confirm_delete.html:6
msgid "Please select the avatars that you would like to delete."
msgstr "请选择要删除的头像。"
#: templates/avatar/confirm_delete.html:9
#, python-format
msgid ""
"You have no avatars to delete. Please <a href=\"%(avatar_change_url)s"
"\">upload one</a> now."
msgstr ""
"您还没有上传自己的头像。现在 <a href=\"%(avatar_change_url)s\">上传一个</a>。"
#: templates/avatar/confirm_delete.html:15
msgid "Delete These"
msgstr "删除"
#: templates/notification/avatar_friend_updated/notice.html:2
#, python-format
msgid ""
"<a href=\"%(user_url)s\">%(avatar_creator)s</a> has updated their avatar <a "
"href=\"%(avatar_url)s\">%(avatar)s</a>."
msgstr ""
#: templates/notification/avatar_updated/notice.html:2
#, python-format
msgid "You have updated your avatar <a href=\"%(avatar_url)s\">%(avatar)s</a>."
msgstr ""
#: templatetags/avatar_tags.py:48
msgid "Default Avatar"
msgstr ""

View File

@ -8,7 +8,8 @@ from django.utils.hashcompat import md5_constructor
from django.utils.encoding import smart_str
from django.db.models import signals
from django.contrib.auth.models import User
#from django.contrib.auth.models import User
from seahub.base.accounts import CcnetUser
try:
from cStringIO import StringIO
@ -33,9 +34,11 @@ def avatar_file_path(instance=None, filename=None, size=None, ext=None):
tmppath = [AVATAR_STORAGE_DIR]
if AVATAR_HASH_USERDIRNAMES:
tmp = md5_constructor(instance.user.username).hexdigest()
tmppath.extend([tmp[0], tmp[1], instance.user.username])
# tmppath.extend([tmp[0], tmp[1], instance.user.username])
tmppath.extend([tmp[0], tmp[1], instance.emailuser])
else:
tmppath.append(instance.user.username)
# tmppath.append(instance.user.username)
tmppath.append(instance.emailuser)
if not filename:
# Filename already stored in database
filename = instance.avatar.name
@ -66,16 +69,17 @@ def find_extension(format):
return format
class Avatar(models.Model):
user = models.ForeignKey(User)
# user = models.ForeignKey(User)
emailuser = models.CharField(max_length=255)
primary = models.BooleanField(default=False)
avatar = models.ImageField(max_length=1024, upload_to=avatar_file_path, blank=True)
date_uploaded = models.DateTimeField(default=datetime.datetime.now)
def __unicode__(self):
return _(u'Avatar for %s') % self.user
return _(u'Avatar for %s') % self.emailuser
def save(self, *args, **kwargs):
avatars = Avatar.objects.filter(user=self.user)
avatars = Avatar.objects.filter(emailuser=self.emailuser)
if self.pk:
avatars = avatars.exclude(pk=self.pk)
if AVATAR_MAX_AVATARS_PER_USER > 1:
@ -84,11 +88,11 @@ class Avatar(models.Model):
avatars.update(primary=False)
else:
avatars.delete()
invalidate_cache(self.user)
invalidate_cache(self.emailuser)
super(Avatar, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
invalidate_cache(self.user)
invalidate_cache(self.emailuser)
super(Avatar, self).delete(*args, **kwargs)
def thumbnail_exists(self, size):
@ -96,7 +100,7 @@ class Avatar(models.Model):
def create_thumbnail(self, size, quality=None):
# invalidate the cache of the thumbnail with the given size first
invalidate_cache(self.user, size)
invalidate_cache(self.emailuser, size)
try:
orig = self.avatar.storage.open(self.avatar.name, 'rb').read()
image = Image.open(StringIO(orig))

View File

@ -1,7 +1,7 @@
{% extends "avatar/base.html" %}
{% extends "myhome_base.html" %}
{% load i18n avatar_tags %}
{% block content %}
{% block main_panel %}
<p>{% trans "Your current avatar: " %}</p>
{% avatar user %}
{% if not avatars %}

View File

@ -1,21 +1,26 @@
{% extends "avatar/base.html" %}
{% extends "myhome_base.html" %}
{% load i18n avatar_tags %}
{% block content %}
{% block main_panel %}
<h2>添加或修改头像</h2>
<p>{% trans "Your current avatar: " %}</p>
{% avatar user %}
{% if not avatars %}
<p>{% trans "You haven't uploaded an avatar yet. Please upload one now." %}</p>
{% else %}
<form method="POST" action="{% url avatar_change %}">
<ul>
{{ primary_avatar_form.as_ul }}
</ul>
<label>从已有头像中选择:</label>
{% for boundfield in primary_avatar_form %}
{{ boundfield }}
{% endfor %}
<p>{% csrf_token %}<input type="submit" value="{% trans "Choose new Default" %}" /></p>
</form>
{% endif %}
<form enctype="multipart/form-data" method="POST" action="{% url avatar_add %}">
{{ upload_avatar_form.as_p }}
<label for="id_avatar">上传新头像:</label>
{% for boundfield in upload_avatar_form %}
{{ boundfield }}
{% endfor %}
<p>{% csrf_token %}<input type="submit" value="{% trans "Upload New Image" %}" /></p>
</form>
{% endblock %}

View File

@ -1,16 +1,20 @@
{% extends "avatar/base.html" %}
{% extends "myhome_base.html" %}
{% load i18n %}
{% block content %}
{% block main_panel %}
<!--
<p>{% trans "Please select the avatars that you would like to delete." %}</p>
-->
<h2>删除头像</h2>
{% if not avatars %}
{% url avatar_change as avatar_change_url %}
<p>{% blocktrans %}You have no avatars to delete. Please <a href="{{ avatar_change_url }}">upload one</a> now.{% endblocktrans %}</p>
{% else %}
<form method="POST" action="{% url avatar_delete %}">
<ul>
{{ delete_avatar_form.as_ul }}
</ul>
<lable>请选择要删除的头像:</lable>
{% for boundfield in delete_avatar_form %}
{{ boundfield }}
{% endfor %}
<p>{% csrf_token %}<input type="submit" value="{% trans "Delete These" %}" /></p>
</form>
{% endif %}

View File

@ -5,7 +5,9 @@ from django.utils.translation import ugettext as _
from django.utils.hashcompat import md5_constructor
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
#from django.contrib.auth.models import User
from seahub.base.accounts import CcnetUser
from seaserv import get_ccnetuser
from avatar.settings import (AVATAR_GRAVATAR_BACKUP, AVATAR_GRAVATAR_DEFAULT,
AVATAR_DEFAULT_SIZE)
@ -34,12 +36,14 @@ def avatar_url(user, size=AVATAR_DEFAULT_SIZE):
@cache_result
@register.simple_tag
def avatar(user, size=AVATAR_DEFAULT_SIZE):
if not isinstance(user, User):
if not isinstance(user, CcnetUser):
try:
user = User.objects.get(username=user)
# user = User.objects.get(username=user)
user = get_ccnetuser(username=user)
alt = unicode(user)
url = avatar_url(user, size)
except User.DoesNotExist:
# except User.DoesNotExist:
except:
url = get_default_avatar_url()
alt = _("Default Avatar")
else:

View File

@ -1,7 +1,10 @@
from django.conf import settings
from django.core.cache import cache
from django.contrib.auth.models import User
#from django.contrib.auth.models import User
from seahub.base.accounts import CcnetUser
from seaserv import get_ccnetuser
from avatar.settings import (AVATAR_DEFAULT_URL, AVATAR_CACHE_TIMEOUT,
AUTO_GENERATE_AVATAR_SIZES, AVATAR_DEFAULT_SIZE)
@ -12,7 +15,7 @@ def get_cache_key(user_or_username, size, prefix):
"""
Returns a cache key consisten of a username and image size.
"""
if isinstance(user_or_username, User):
if isinstance(user_or_username, CcnetUser):
user_or_username = user_or_username.username
return '%s_%s_%s' % (prefix, user_or_username, size)
@ -44,6 +47,10 @@ def invalidate_cache(user, size=None):
cache.delete(get_cache_key(user, size, prefix))
def get_default_avatar_url():
"""(e.g.)
base_url = '/media/'
AVATAR_DEFAULT_URL = '/avatars/default.png'
"""
base_url = getattr(settings, 'STATIC_URL', None)
if not base_url:
base_url = getattr(settings, 'MEDIA_URL', '')
@ -60,17 +67,21 @@ def get_default_avatar_url():
return '%s%s' % (base_url, AVATAR_DEFAULT_URL)
def get_primary_avatar(user, size=AVATAR_DEFAULT_SIZE):
if not isinstance(user, User):
if not isinstance(user, CcnetUser):
try:
user = User.objects.get(username=user)
except User.DoesNotExist:
# user = User.objects.get(username=user)
user = get_ccnetuser(username=user)
# except User.DoesNotExist:
except:
return None
try:
# Order by -primary first; this means if a primary=True avatar exists
# it will be first, and then ordered by date uploaded, otherwise a
# primary=False avatar will be first. Exactly the fallback behavior we
# want.
avatar = user.avatar_set.order_by("-primary", "-date_uploaded")[0]
# avatar = user.avatar_set.order_by("-primary", "-date_uploaded")[0]
from seahub.avatar.models import Avatar
avatar = Avatar.objects.filter(emailuser=user.email, primary=1)[0]
except IndexError:
avatar = None
if avatar:

View File

@ -10,7 +10,8 @@ from avatar.forms import PrimaryAvatarForm, DeleteAvatarForm, UploadAvatarForm
from avatar.models import Avatar
from avatar.settings import AVATAR_MAX_AVATARS_PER_USER, AVATAR_DEFAULT_SIZE
from avatar.signals import avatar_updated
from avatar.util import get_primary_avatar, get_default_avatar_url
from avatar.util import get_primary_avatar, get_default_avatar_url, \
invalidate_cache
def _get_next(request):
@ -35,7 +36,8 @@ def _get_next(request):
def _get_avatars(user):
# Default set. Needs to be sliced, but that's it. Keep the natural order.
avatars = user.avatar_set.all()
# avatars = user.avatar_set.all()
avatars = Avatar.objects.filter(emailuser=user.email)
# Current avatar
primary_avatar = avatars.order_by('-primary')[:1]
@ -62,14 +64,14 @@ def add(request, extra_context=None, next_override=None,
if request.method == "POST" and 'avatar' in request.FILES:
if upload_avatar_form.is_valid():
avatar = Avatar(
user = request.user,
emailuser = request.user.username,
primary = True,
)
image_file = request.FILES['avatar']
avatar.avatar.save(image_file.name, image_file)
avatar.save()
request.user.message_set.create(
message=_("Successfully uploaded a new avatar."))
# request.user.message_set.create(
# message=_("Successfully uploaded a new avatar."))
avatar_updated.send(sender=Avatar, user=request.user, avatar=avatar)
return HttpResponseRedirect(next_override or _get_next(request))
return render_to_response(
@ -106,8 +108,8 @@ def change(request, extra_context=None, next_override=None,
avatar.primary = True
avatar.save()
updated = True
request.user.message_set.create(
message=_("Successfully updated your avatar."))
# request.user.message_set.create(
# message=_("Successfully updated your avatar."))
if updated:
avatar_updated.send(sender=Avatar, user=request.user, avatar=avatar)
return HttpResponseRedirect(next_override or _get_next(request))
@ -142,9 +144,15 @@ def delete(request, extra_context=None, next_override=None, *args, **kwargs):
a.save()
avatar_updated.send(sender=Avatar, user=request.user, avatar=avatar)
break
Avatar.objects.filter(id__in=ids).delete()
request.user.message_set.create(
message=_("Successfully deleted the requested avatars."))
# NOTE: `Avatar.objects.filter(id__in=ids).delete()` will NOT work
# correctly. Sinct delete() on QuerySet will not call delete
# method on avatar object.
for a in Avatar.objects.filter(id__in=ids):
a.delete()
# request.user.message_set.create(
# message=_("Successfully deleted the requested avatars."))
return HttpResponseRedirect(next_override or _get_next(request))
return render_to_response(
'avatar/confirm_delete.html',

View File

@ -1,5 +1,5 @@
{% extends "myhome_base.html" %}
{% load seahub_tags %}
{% load seahub_tags avatar_tags %}
{% block nav_group_class %}class="cur"{% endblock %}
@ -8,14 +8,14 @@
<h3>管理员</h3>
<ul>
{% for member in managers %}
<li><img src="{{MEDIA_URL}}img/default-person-16.png" alt="{{ member.short_username }}的图标" class="group-member-icon" /><span class="group-member-name">{{ member.short_username }}</span></li>
<li>{% avatar member.user_name 16 %}<span class="group-member-name">{{ member.short_username }}</span></li>
{% endfor %}
<h3>成员</h3>
{% if common_members %}
<ul>
{% for member in common_members %}
<li><img src="{{MEDIA_URL}}img/default-person-16.png" alt="{{ member.short_username }}的图标" class="group-member-icon" /><span class="group-member-name">{{ member.short_username }}</span></li>
<li>{% avatar member.user_name 16 %}<span class="group-member-name">{{ member.short_username }}</span></li>
{% endfor %}
</ul>
{% else %}

View File

@ -26,7 +26,7 @@ TIME_ZONE = 'Asia/Shanghai'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'zh-CN'
LANGUAGE_CODE = 'zh_CN'
SITE_ID = 1
@ -174,10 +174,10 @@ else:
globals()[attr] = getattr(local_settings, attr)
#avatar
#AVATAR_STORAGE_DIR = 'avatars'
#AVATAR_GRAVATAR_BACKUP = False
#AVATAR_DEFAULT_URL = MEDIA_URL + '/avatars/default.png'
AVATAR_STORAGE_DIR = 'avatars'
AVATAR_GRAVATAR_BACKUP = False
AVATAR_DEFAULT_URL = '/avatars/default.png'
AUTO_GENERATE_AVATAR_SIZES = (80, 16)
LOGIN_URL = SITE_ROOT + 'accounts/login'

View File

@ -1,3 +0,0 @@
{% extends "accounts.html" %}
{% block title %}个人头像{% endblock %}

View File

@ -1,31 +0,0 @@
{% extends "avatar/base.html" %}
{% load avatar_tags %}
{% block content %}
<div class="avatar_op">
<h2>添加或修改头像</h2>
<div class="pic">
<h3>当前头像:</h3>
{% avatar user %}
</div>
<div class="text">
{% if not avatars %}
<p>您还没有自己的头像。</p>
{% else %}
<h3>从已有头像中选择:</h3>
<form method="POST" action="">
<ul>
{{ primary_avatar_form.as_ul }}
</ul>
<div class="clear"></div>
<input type="submit" value="确定" />
</form>
{% endif %}
<h3>上传新头像:</h3>
<form enctype="multipart/form-data" method="POST" action="">
<input type="file" name="avatar" value="Avatar Image" /><br />
<input type="submit" value="提交" />
</form>
</div>
</div>
{% endblock %}

View File

@ -1,18 +0,0 @@
{% extends "avatar/base.html" %}
{% block content %}
<div class="avatar_op">
<h2>删除头像</h2>
{% if not avatars %}
<p>您还没有上传自己的头像。现在 <a href="{% url avatar_change %}">上传一个</a>.</p>
{% else %}
<form method="POST" action="">
<ul>
{{ delete_avatar_form.as_ul }}
</ul>
<div class="clear"></div>
<input type="submit" value="删除" />
</form>
{% endif %}
</div>
{% endblock %}

View File

@ -1,7 +1,13 @@
{% extends "myhome_base.html" %}
{% load avatar_tags %}
{% block nav_myhome_class %}class="cur"{% endblock %}
{% block left_panel %}
<h3>个人头像</h3>
<a href="{{ SITE_ROOT }}avatar/change/">{% avatar request.user 80 %}</a>
<p><a href="{{ SITE_ROOT }}avatar/change/">修改</a>
<a href="{{ SITE_ROOT }}avatar/delete/">删除</a></p>
<h3>已用空间</h3>
<p>{{ quota_usage|filesizeformat }} / 2 GB</p>

View File

@ -298,11 +298,11 @@ def get_user(user_id):
def get_ccnetuser(username=None, userid=None):
# Get emailuser from db
if username != None:
if username:
emailuser = ccnet_rpc.get_emailuser(username)
if userid != None:
if userid:
emailuser = ccnet_rpc.get_emailuser_by_id(userid)
if emailuser == None:
if not emailuser:
return None
# And convert to ccnetuser