myModelVersionned.py 3.3 KB
Newer Older
Florent Chehab's avatar
Florent Chehab committed
1
2
from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet
from backend.signals import new_revision_saved
3
from rest_framework import serializers, permissions, 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
Florent Chehab's avatar
Florent Chehab committed
9
10
11
12


class MyModelVersionned(MyModel):

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

Florent Chehab's avatar
Florent Chehab committed
22
23
24
25
26
    class Meta:
        abstract = True


class MyModelVersionnedSerializer(MyModelSerializer):
27
28
29
30
31
32
33
34
35
36
37
    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
38
39
40

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


class MyModelVersionnedViewSet(MyModelViewSet):
    serializer_class = MyModelVersionnedSerializer
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95


class VersionSerializer(serializers.ModelSerializer):
    # serialized_data = serializers.JSONField()
    data = serializers.SerializerMethodField()

    def get_data(self, obj):
        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()
            if obj_serializer is None:
                return "THE PROGRAMMER FORGOT TO SET THE SERIALIZER IN THE MODEL"
            else:
                new_context = dict(self.context)
                new_context['view'].action = 'list'
                return obj_serializer(tmp.object, context=new_context).data
        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
    permission_classes = (permissions.IsAuthenticated,)
    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)

    # queryset = get_queryset()