Commit 370ad7f3 authored by Hamza Dely's avatar Hamza Dely
Browse files

[comptes/views] Gestion correcte des avatars via l'interface Web

parent 0a80e2c0
# -*- coding: utf-8 -*-
# Generated by Django 1.11.10 on 2018-02-07 21:31
from __future__ import unicode_literals
import comptes.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('comptes', '0004_auto_20171213_1017'),
]
operations = [
migrations.AlterField(
model_name='adherent',
name='avatar',
field=models.ImageField(blank=True, default=None, max_length=255, null=True, upload_to=comptes.models.upload_to_avatars),
),
]
......@@ -395,6 +395,12 @@ class AdherentManager(BaseUserManager):
new_adherent.set_password(password)
new_adherent.save()
def upload_to_avatars(instance, _):
"""
Renvoie le chemin relatif d'enregistrement des avatars d'un adhérent
"""
return "avatars/%s" % instance.uuid
class Adherent(AbstractBaseUser):
"""
Un adhérent de l'association.
......@@ -404,6 +410,7 @@ class Adherent(AbstractBaseUser):
- prenom [varchar(255)] -> Prénom de l'adhérent
- email [varchar(254)] -> Email de l'adhérent
- sexe[0-1] [varchar(1)] -> Sexe de l'adhérent
- avatar[0-1] [varchar(255)] -> Avatar de l'adhérent
- type [varchar(255)] -> Type d'adhérent
- telephone [varchar(255)] -> Numéro de téléphone de l'adhérent
- adresse [varchar] -> Adresse postale de l'adhérent
......@@ -497,7 +504,7 @@ class Adherent(AbstractBaseUser):
)
avatar = models.ImageField(
max_length=255,
upload_to="avatars/",
upload_to=upload_to_avatars,
blank=True,
null=True,
default=None,
......
......@@ -2,15 +2,49 @@
Signaux utilisés pour interagir avec les modèles de l'application Comptes.
"""
from django.db.models.signals import post_save
import os
from django.conf import settings
from django.db.models import signals
from django.dispatch import receiver
from PIL import Image
from comptes.models import Adherent
@receiver(post_save, sender=Adherent)
@receiver(signals.post_save, sender=Adherent)
def send_mail_after_registration(sender, instance=None, created=False, **kwargs):
"""
Envoie un mail de bienvenue à l'adhérent après qu'il ait été créé.
"""
if created:
instance.email_user_from_template('Activation de ta note Kfet', 'adherent_bienvenue')
@receiver(signals.pre_save, sender=Adherent)
def delete_old_avatar_if_changed(sender, instance=None, **kwargs):
"""
Supprime l'ancien avatar d'un adhérent
"""
if instance.id is None:
return None
old_avatar = Adherent.objects.only("avatar").get(id=instance.id).avatar
if not old_avatar:
return None
if instance.avatar != old_avatar and os.path.isfile(old_avatar.path):
os.remove(old_avatar.path)
@receiver(signals.post_save, sender=Adherent)
def resize_avatar_if_necessary(sender, instance=None, **kwargs):
"""
Modifie la taille de l'avatar après son envoi sur le serveur
"""
if not instance.avatar:
return None
if (instance.avatar.width > settings.THUMBNAIL_SIZE[1]
or instance.avatar.height > settings.THUMBNAIL_SIZE[0]):
image = Image.open(instance.avatar.path)
image.thumbnail(settings.THUMBNAIL_SIZE)
image.save(instance.avatar.path, "PNG")
......@@ -333,16 +333,6 @@ class AdherentAvatarView(NoteMixin, LoginRequiredMixin, PermissionRequiredMixin,
model = Adherent
fields = ['avatar']
def form_valid(self, form):
"""
Enregistre l'image sur la machine et l'associe avec l'adhérent.
"""
adherent = get_object_or_404(Adherent, pk=self.kwargs['pk'])
seed = "%s|%s" % (adherent.uuid, timezone.now().isoformat())
self.object.avatar.name = hashlib.sha512(seed.encode('utf-8')).hexdigest()
return super().form_valid(form)
def get_success_url(self):
adherent = get_object_or_404(Adherent, pk=self.kwargs['pk'])
return reverse_lazy('comptes:detail', kwargs={'pk' : adherent.id})
......
......@@ -235,6 +235,8 @@ else:
# Custom enabled applications
THUMBNAIL_SIZE = (250, 250)
ENABLED_APPS = [
'comptes',
'activites',
......
......@@ -32,7 +32,7 @@ urlpatterns = [
# API
url(r'^api/', include('note_kfet.api', namespace="api")),
# URL de fichiers multimédias, accessibles après autorisation
url(r'^media/(?P<type>[a-zA-Z0-9]+)/(?P<id>[a-f0-9]+)/', NginxMediaView.as_view(), name="nginx-media"),
url(r'^media/(?P<type>[a-zA-Z0-9]+)/(?P<id>[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12})/', NginxMediaView.as_view(), name="nginx-media"),
]
if settings.DEBUG:
......
......@@ -2,11 +2,14 @@
Vues spéciales
"""
from django.conf import settings
from django.http.response import HttpResponse
from django.views.generic.base import View
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from PIL import Image
### Vue pour servir les images
class NginxMediaView(LoginRequiredMixin, View):
......@@ -18,6 +21,7 @@ class NginxMediaView(LoginRequiredMixin, View):
response = HttpResponse()
media_type = kwargs.get('type', '')
media_id = kwargs.get('id', '')
response["Content-Type"] = 'image/jpeg'
media = Image.open("%s/%s/%s" % (settings.MEDIA_ROOT, media_type, media_id))
response["Content-Type"] = Image.MIME.get(media.format)
response["X-Accel-Redirect"] = "/internal/%s/%s" % (media_type, media_id)
return response
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment