myModelVersionned.py 3.24 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
15
16
17
18
19
20
    def get_serializer(self):
        """
            This function is required for handling
            versionning easily.
            You have to put the correct value in each subclass
        """
        return None

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


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

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


class MyModelVersionnedViewSet(MyModelViewSet):
    serializer_class = MyModelVersionnedSerializer
50
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


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()