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)