Commit 96f54fae authored by Hamza Dely's avatar Hamza Dely
Browse files

[comptes/serializers] Le changement d'avatar via l'API est désormais possible

parent 6cb6d99a
......@@ -490,13 +490,13 @@ class Adherent(AbstractBaseUser):
CHAMPS_VISIBLES = CumulativeDict([
(m_droits.Acl.BASIQUE, ['nom', 'prenom', 'sexe', 'email', 'is_active', 'supprime', 'adhesions', 'aliases']),
(m_droits.Acl.ETENDU, ['telephone', 'adresse', 'remunere', 'remarque', 'accreditations']),
(m_droits.Acl.ETENDU, ['telephone', 'adresse', 'remunere', 'remarque', 'accreditations', 'avatar']),
(m_droits.Acl.TOTAL, ['pbsante', 'is_staff']),
])
CHAMPS_MODIFIABLES = CumulativeDict([
(m_droits.Acl.BASIQUE, ['nom', 'prenom', 'sexe', 'email',]),
(m_droits.Acl.ETENDU, ['telephone', 'adresse', 'remunere', 'remarque',]),
(m_droits.Acl.ETENDU, ['telephone', 'adresse', 'remunere', 'remarque', 'avatar']),
(m_droits.Acl.TOTAL, ['pbsante',]),
])
......
......@@ -6,10 +6,9 @@ from django.contrib.auth.password_validation import validate_password as django_
from rest_framework import serializers
from note_kfet.mixins import DynamicFieldsMixin
from comptes.models import (
Section, Alias, Historique, Droit, Accreditation, Adhesion, Adherent
)
from note_kfet import mixins
from note_kfet.fields import Base64ImageField
from comptes.models import Section, Alias, Historique, Droit, Accreditation, Adhesion, Adherent
class SectionSerializer(serializers.ModelSerializer):
"""
......@@ -29,7 +28,7 @@ class DroitSerializer(serializers.ModelSerializer):
fields = ['id', 'description', 'niveau']
read_only_fields = ['id', 'description', 'niveau']
class AccreditationSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
class AccreditationSerializer(mixins.DynamicFieldsMixin, serializers.ModelSerializer):
"""
Sérialiseur pour le modèle Accréditation
"""
......@@ -71,7 +70,7 @@ class AliasSerializer(serializers.ModelSerializer):
### Sérialiseurs pour le modèle Adhérent
class AdherentSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
class AdherentSerializer(mixins.DynamicFieldsMixin, serializers.ModelSerializer):
"""
Sérialiseur pour le modèle Adhérent
"""
......@@ -86,7 +85,7 @@ class AdherentSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
'id', 'pseudo', 'nom', 'prenom', 'email', 'sexe',
'type', 'telephone', 'adresse', 'remunere', 'pbsante', 'remarque',
'supprime', 'is_staff', 'is_active', 'aliases', 'adhesions', 'last_adhesion',
'accreditations', 'password', 'section',
'accreditations', 'password', 'section', 'avatar',
]
read_only_fields = ['id']
extra_kwargs = {'password': {'write_only': True}}
......
#-*- coding: utf-8 -*-
from django.db import models
from rest_framework import serializers
from PIL import Image
from note_kfet import mixins
class Base64ImageField(mixins.Base64FieldMixin, serializers.ImageField):
"""
Champ permettant d'encoder/décoder une image en base 64
"""
def get_file_type(self, obj):
im = Image.open(obj.path)
return Image.MIME.get(im.format)
# Par défaut, on veut pouvoir communiquer les fichiers en base 64, donc on
# override le champ de sérialisation par défaut
serializers.ModelSerializer.serializer_field_mapping[models.ImageField] = Base64ImageField
......@@ -2,9 +2,14 @@
Mixins pour les vues de la Note Kfet.
"""
import uuid
import base64
import binascii
from collections import OrderedDict
from django.forms import BaseFormSet
from django.forms import BaseFormSet, ValidationError
from django.core.files.base import ContentFile
from django.core.validators import EMPTY_VALUES
class NoteMixin(object):
"""
......@@ -90,3 +95,49 @@ class DynamicFieldsMixin(object):
super().__init__(*args, **kwargs)
for field in set(self.fields) - fields:
self.fields.pop(field)
class Base64FieldMixin(object):
"""
Un mixin permettant de sérialiser et désérialiser un fichier en base 64
Adapté de DRF Extra Fields (https://github.com/Hipo/drf-extra-fields/)
"""
def to_representation(self, obj):
"""
Renvoie la représentation en base 64 de l'objet donné en paramètre
"""
try:
with open(obj.path, mode='rb') as f:
return "%s;base64,%s" % (
self.get_file_type(obj),
base64.b64encode(f.read()).decode(),
)
except ValueError:
# Pas de fichier correspondant
return None
except Exception:
raise IOError("Erreur lors de l'encodage des données")
def to_internal_value(self, b64_data):
"""
Renvoie un fichier en mémoire obtenu en décodant les données reçues
encodées en base 64
"""
if b64_data in EMPTY_VALUES:
return None
if not isinstance(b64_data, str):
raise ValidationError("Les données encodées ne sont pas sous forme d'une chaîne en base 64")
if ";base64," in b64_data:
header, b64_data = b64_data.split(';base64,')
try:
data = base64.b64decode(b64_data)
except (TypeError, binascii.Error, IOError, ValueError):
raise ValidationError("Données encodées en base 64 invalides")
file_obj = ContentFile(data, name=str(uuid.uuid4()))
return super().to_internal_value(file_obj)
def get_file_type(self, obj):
raise NotImplemented
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