Browse Source

#610: small db struct changes, fix serializer, test user creation and misago_avatars template tag

Rafał Pitoń 8 years ago
parent
commit
e3fbc9fe1b

+ 0 - 8
misago/users/avatars/store.py

@@ -48,14 +48,6 @@ def get_user_avatar_tokens(user):
     return tokens
     return tokens
 
 
 
 
-def store_temporary_avatar(user, image):
-    avatars_dir = get_existing_avatars_dir(user)
-    avatar_file = '%s_tmp.png' % user.pk
-
-    normalize_image(image)
-    image.save(os.path.join(avatars_dir, avatar_file), "PNG")
-
-
 def store_original_avatar(user):
 def store_original_avatar(user):
     org_path = avatar_file_path(user, 'org')
     org_path = avatar_file_path(user, 'org')
     if org_path.exists():
     if org_path.exists():

+ 26 - 5
misago/users/avatars/store_.py

@@ -17,6 +17,13 @@ def normalize_image(image):
     return image.copy().convert('RGBA')
     return image.copy().convert('RGBA')
 
 
 
 
+def delete_avatar(user, exclude=None):
+    exclude = exclude or []
+    for avatar in user.avatar_set.exclude(id__in=exclude):
+        avatar.image.delete(False)
+    user.avatar_set.exclude(id__in=exclude).delete()
+
+
 def store_avatar(user, image):
 def store_avatar(user, image):
     from ..models import Avatar
     from ..models import Avatar
     image = normalize_image(image)
     image = normalize_image(image)
@@ -40,11 +47,25 @@ def store_avatar(user, image):
         delete_avatar(user, exclude=[a.id for a in avatars])
         delete_avatar(user, exclude=[a.id for a in avatars])
 
 
 
 
-def delete_avatar(user, exclude=None):
-    exclude = exclude or []
-    for avatar in user.avatar_set.exclude(id__in=exclude):
-        avatar.image.delete(False)
-    user.avatar_set.exclude(id__in=exclude).delete()
+def store_temporary_avatar(user, image):
+    image_stream = BytesIO()
+
+    normalize_image(image)
+    image.save(image_stream, "PNG")
+
+    if user.avatar_tmp:
+        user.avatar_tmp.delete(False)
+
+    user.avatar_tmp = ContentFile(image_stream.getvalue(), 'avatar')
+    user.save(update_fields=['avatar_tmp'])
+
+
+def store_original_avatar(user):
+    if user.avatar_src:
+        user.avatar_src.delete(False)
+    user.avatar_src = user.avatar_tmp.path
+    user.avatar_tmp = None
+    user.save(update_fields=['avatar_tmp', 'avatar_src'])
 
 
 
 
 def upload_to(instance, filename):
 def upload_to(instance, filename):

+ 1 - 1
misago/users/avatars/uploaded.py

@@ -13,7 +13,7 @@ from . import store
 
 
 
 
 ALLOWED_EXTENSIONS = ('.gif', '.png', '.jpg', '.jpeg')
 ALLOWED_EXTENSIONS = ('.gif', '.png', '.jpg', '.jpeg')
-ALLOWED_MIME_TYPES = ('image/gif', 'image/jpeg', 'image/png')
+ALLOWED_MIME_TYPES = ('image/gif', 'image/jpeg', 'image/png', 'image/mpo')
 
 
 
 
 def validate_file_size(uploaded_file):
 def validate_file_size(uploaded_file):

+ 1 - 1
misago/users/migrations/0001_initial.py

@@ -48,7 +48,7 @@ class Migration(migrations.Migration):
                 ('groups', models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Group', blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of his/her group.', verbose_name='groups')),
                 ('groups', models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Group', blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of his/her group.', verbose_name='groups')),
                 ('roles', models.ManyToManyField(to='misago_acl.Role')),
                 ('roles', models.ManyToManyField(to='misago_acl.Role')),
                 ('user_permissions', models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Permission', blank=True, help_text='Specific permissions for this user.', verbose_name='user permissions')),
                 ('user_permissions', models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Permission', blank=True, help_text='Specific permissions for this user.', verbose_name='user permissions')),
-                ('avatar_temp', models.ImageField(upload_to=misago.users.avatars.store.upload_to, null=True, blank=True)),
+                ('avatar_tmp', models.ImageField(upload_to=misago.users.avatars.store.upload_to, null=True, blank=True)),
                 ('avatar_src', models.ImageField(upload_to=misago.users.avatars.store.upload_to, null=True, blank=True)),
                 ('avatar_src', models.ImageField(upload_to=misago.users.avatars.store.upload_to, null=True, blank=True)),
                 ('avatar_crop', models.CharField(max_length=255, null=True, blank=True)),
                 ('avatar_crop', models.CharField(max_length=255, null=True, blank=True)),
                 ('avatars', JSONField(null=True, blank=True)),
                 ('avatars', JSONField(null=True, blank=True)),

+ 4 - 1
misago/users/models/user.py

@@ -129,6 +129,9 @@ class UserManager(BaseUserManager):
 
 
         if set_default_avatar:
         if set_default_avatar:
             avatars.set_default_avatar(user)
             avatars.set_default_avatar(user)
+        else:
+            # just for test purposes
+            user.avatars = [{'size': 400, 'url': '//placekitten.com/400/400'}]
 
 
         authenticated_role = Role.objects.get(special_role='authenticated')
         authenticated_role = Role.objects.get(special_role='authenticated')
         if authenticated_role not in user.roles.all():
         if authenticated_role not in user.roles.all():
@@ -225,7 +228,7 @@ class User(AbstractBaseUser, PermissionsMixin):
     )
     )
     is_active_staff_message = models.TextField(null=True, blank=True)
     is_active_staff_message = models.TextField(null=True, blank=True)
 
 
-    avatar_temp = models.ImageField(upload_to=avatars.store.upload_to, null=True, blank=True)
+    avatar_tmp = models.ImageField(upload_to=avatars.store.upload_to, null=True, blank=True)
     avatar_src = models.ImageField(upload_to=avatars.store.upload_to, null=True, blank=True)
     avatar_src = models.ImageField(upload_to=avatars.store.upload_to, null=True, blank=True)
     avatar_crop = models.CharField(max_length=255, null=True, blank=True)
     avatar_crop = models.CharField(max_length=255, null=True, blank=True)
     avatars = JSONField(null=True, blank=True)
     avatars = JSONField(null=True, blank=True)

+ 5 - 5
misago/users/serializers/user.py

@@ -50,7 +50,7 @@ class AuthenticatedUserSerializer(serializers.ModelSerializer):
             'full_title',
             'full_title',
             'short_title',
             'short_title',
             'rank',
             'rank',
-            'avatar_hash',
+            'avatars',
             'new_notifications',
             'new_notifications',
             'limits_private_thread_invites_to',
             'limits_private_thread_invites_to',
             'unread_private_threads',
             'unread_private_threads',
@@ -114,7 +114,7 @@ class BasicUserSerializer(BaseSerializer):
             'id',
             'id',
             'username',
             'username',
             'slug',
             'slug',
-            'avatar_hash',
+            'avatars',
             'absolute_url',
             'absolute_url',
         )
         )
 
 
@@ -132,7 +132,7 @@ class UserSerializer(BaseSerializer):
             'username',
             'username',
             'slug',
             'slug',
             'joined_on',
             'joined_on',
-            'avatar_hash',
+            'avatars',
             'title',
             'title',
             'short_title',
             'short_title',
             'rank',
             'rank',
@@ -168,7 +168,7 @@ class ScoredUserSerializer(UserSerializer):
             'username',
             'username',
             'slug',
             'slug',
             'joined_on',
             'joined_on',
-            'avatar_hash',
+            'avatars',
             'title',
             'title',
             'rank',
             'rank',
             'signature',
             'signature',
@@ -201,7 +201,7 @@ class UserProfileSerializer(UserSerializer):
             'email',
             'email',
             'joined_on',
             'joined_on',
             'is_avatar_locked',
             'is_avatar_locked',
-            'avatar_hash',
+            'avatars',
             'title',
             'title',
             'rank',
             'rank',
             'signature',
             'signature',

+ 5 - 5
misago/users/templatetags/misago_avatars.py

@@ -7,11 +7,11 @@ register = template.Library()
 
 
 @register.filter(name='avatar')
 @register.filter(name='avatar')
 def avatar(user, size=200):
 def avatar(user, size=200):
-    return reverse('misago:user-avatar', kwargs={
-        'pk': user.pk,
-        'hash': user.avatar_hash,
-        'size': size
-    })
+    found_avatar = user.avatars[0]
+    for user_avatar in user.avatars:
+        if user_avatar['size'] >= size:
+            found_avatar = user_avatar
+    return found_avatar['url']
 
 
 
 
 @register.simple_tag
 @register.simple_tag

+ 21 - 7
misago/users/tests/test_misagoavatars_tags.py

@@ -9,23 +9,37 @@ class TemplateTagsTests(TestCase):
         User = get_user_model()
         User = get_user_model()
         user = User.objects.create_user('Bob', 'bob@test.com', 'pass123')
         user = User.objects.create_user('Bob', 'bob@test.com', 'pass123')
 
 
+        user.avatars = [
+            {
+                'size': 400,
+                'url': '/avatar/400.png'
+            },
+            {
+                'size': 128,
+                'url': '/avatar/400.png'
+            },
+            {
+                'size': 30,
+                'url': '/avatar/30.png'
+            },
+        ]
+
         tpl_content = """
         tpl_content = """
 {% load misago_avatars %}
 {% load misago_avatars %}
 
 
 {{ user|avatar }}
 {{ user|avatar }}
 {{ user|avatar:100 }}
 {{ user|avatar:100 }}
+{{ user|avatar:30 }}
+{{ user|avatar:10 }}
 """
 """
 
 
         tpl = Template(tpl_content)
         tpl = Template(tpl_content)
         render = tpl.render(Context({'user': user})).strip().splitlines()
         render = tpl.render(Context({'user': user})).strip().splitlines()
 
 
-        pk = user.pk
-        avatar_hash = user.avatar_hash
-
-        self.assertEqual(render[0].strip(),
-                         '/user-avatar/%s/200/%s.png' % (avatar_hash, pk))
-        self.assertEqual(render[1].strip(),
-                         '/user-avatar/%s/100/%s.png' % (avatar_hash, pk))
+        self.assertEqual(render[0].strip(), user.avatars[0]['url'])
+        self.assertEqual(render[1].strip(), user.avatars[1]['url'])
+        self.assertEqual(render[2].strip(), user.avatars[2]['url'])
+        self.assertEqual(render[3].strip(), user.avatars[2]['url'])
 
 
     def test_blankavatar_tag(self):
     def test_blankavatar_tag(self):
         """{% blankavatar %} tag returns url to default image"""
         """{% blankavatar %} tag returns url to default image"""