myModelVersionned.py 3.23 KB
Newer Older
1
from backend.models.abstract.my_model import MyModel, MyModelSerializer, MyModelViewSet
Florent Chehab's avatar
Florent Chehab committed
2
from backend.signals import new_revision_saved
3
from rest_framework import serializers, mixins, viewsets
Florent Chehab's avatar
Florent Chehab committed
4
import reversion
5 6 7 8
from reversion.models import Version
from django.contrib.contenttypes.models import ContentType
from django.core.serializers.base import DeserializationError
from django.core import serializers as djangoSerializers
9
from backend.utils import get_viewset_permissions
10
from backend.custom import MySerializerWithJSON
Florent Chehab's avatar
Florent Chehab committed
11 12 13 14


class MyModelVersionned(MyModel):

15 16
    @classmethod
    def get_serializer(cls):
17 18
        """
            This function is required for handling
19
            versioning easily.
20 21
            You have to put the correct value in each subclass
        """
22
        raise Exception("Get_serializer must be redifined in subclass")
23

Florent Chehab's avatar
Florent Chehab committed
24 25 26 27 28
    class Meta:
        abstract = True


class MyModelVersionnedSerializer(MyModelSerializer):
29 30 31 32 33 34 35 36 37 38 39
    nb_versions = serializers.SerializerMethodField()
    content_type_id = serializers.SerializerMethodField()

    def get_nb_versions(self, obj):
        if self.context['view'].action != 'list':
            versions = Version.objects.get_for_object(obj)
            return len(versions)
        return None

    def get_content_type_id(self, obj):
        return ContentType.objects.get_for_model(self.Meta.model).id
Florent Chehab's avatar
Florent Chehab committed
40

Florent Chehab's avatar
Florent Chehab committed
41
    def save(self, *args, **kwargs):
Florent Chehab's avatar
Florent Chehab committed
42
        user = self.context['request'].user
43
        res = None
Florent Chehab's avatar
Florent Chehab committed
44
        with reversion.create_revision():
Florent Chehab's avatar
Florent Chehab committed
45
            res = self.my_save(*args, **kwargs)
Florent Chehab's avatar
Florent Chehab committed
46 47
            reversion.set_user(user)
        new_revision_saved.send(sender=self.__class__, obj=self.instance)
48
        return res
Florent Chehab's avatar
Florent Chehab committed
49 50 51 52


class MyModelVersionnedViewSet(MyModelViewSet):
    serializer_class = MyModelVersionnedSerializer
53 54


Florent Chehab's avatar
Florent Chehab committed
55
class VersionSerializer(MySerializerWithJSON):
56 57 58
    data = serializers.SerializerMethodField()

    def get_data(self, obj):
Florent Chehab's avatar
Florent Chehab committed
59 60 61
        """
        TODO test
        """
62 63 64 65 66 67 68 69
        data = obj.serialized_data

        try:
            tmp = list(djangoSerializers.deserialize(
                obj.format, data, ignorenonexistent=True))[0]
            print(tmp.object)
            # Version is valid,
            obj_serializer = tmp.object.get_serializer()
Florent Chehab's avatar
Florent Chehab committed
70 71 72
            new_context = dict(self.context)
            new_context['view'].action = 'list'
            return obj_serializer(tmp.object, context=new_context).data
73 74 75 76 77 78 79 80 81 82 83 84
        except (DeserializationError, djangoSerializers.SerializerDoesNotExist):
            obj.delete()  # The version is not valid regarding the model, we should delete it !
            # Might result in inconsistent nb of versions but that's fine.
            return None

    class Meta:
        model = Version
        fields = ('data', 'id')


class VersionViewSet(mixins.ListModelMixin,
                     viewsets.GenericViewSet):  # TODO better presentation
85
    permission_classes = get_viewset_permissions("VersionViewSet")
86 87 88 89 90 91 92 93 94
    serializer_class = VersionSerializer

    def get_queryset(self):
        content_type_id = self.kwargs['content_type_id']
        object_pk = self.kwargs['object_pk']
        ct = ContentType.objects.get_for_id(content_type_id)
        model = ct.model_class()
        obj = model.objects.get(pk=object_pk)
        return Version.objects.get_for_object(obj)