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