#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.web module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #
# or FITNESS FOR A PARTICULAR PURPOSE. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
from django.core.serializers.base import DeserializationError
from django.core.serializers.python import Deserializer as PythonDeserializer, _get_model
from django.core.serializers.json import Serializer as JSONSerializer
from django.utils.encoding import force_text
from django.contrib.contenttypes.models import ContentType
from django.utils import six
from actstream.models import Action
import sys
import json
elements_to_convert = [('actor_object_id', 'actor_content_type'),
('action_object_object_id', 'action_object_content_type'),
('target_object_id', 'target_content_type')]
[docs]class Serializer(JSONSerializer):
"""
Custom JSON serializer that replaces the actstream Action model ids by
their natural key counterpart.
"""
[docs] def get_dump_object(self, obj):
data = {
"model": force_text(obj._meta),
"fields": self._current,
}
if not self.use_natural_primary_keys or not hasattr(obj, 'natural_key'):
data["pk"] = force_text(obj._get_pk_val(), strings_only=True)
if self.use_natural_primary_keys and isinstance(obj, Action):
for element in elements_to_convert:
element_object_id = element[0]
element_content_type = element[1]
element_info = data['fields'][element_content_type]
if element_info:
element_app = element_info[0]
element_model = element_info[1]
element_type = ContentType.objects.get(app_label=element_app, model=element_model)
element_id = data['fields'][element_object_id]
element_object = element_type.get_object_for_this_type(id=int(element_id))
data['fields'][element_object_id] = element_object.natural_key()
return data
[docs]def Deserializer(stream_or_string, **options):
"""
Custom JSON deserializer that will replace the natural keys generated by
the serializer to their id counterpart.
"""
if not isinstance(stream_or_string, (bytes, six.string_types)):
stream_or_string = stream_or_string.read()
if isinstance(stream_or_string, bytes):
stream_or_string = stream_or_string.decode('utf-8')
try:
objects = json.loads(stream_or_string)
for d in objects:
# Look up the model and starting build a dict of data for it.
Model = _get_model(d["model"])
if Model == Action:
for element in elements_to_convert:
element_object_id = element[0]
element_content_type = element[1]
element_info = d['fields'][element_content_type]
if element_info:
element_app = element_info[0]
element_model = element_info[1]
element_type = ContentType.objects.get(app_label=element_app, model=element_model)
element_natural_key = d['fields'][element_object_id]
element_object = element_type.model_class().objects.get_by_natural_key(*element_natural_key)
d['fields'][element_object_id] = str(element_object.id)
for obj in PythonDeserializer(objects, **options):
yield obj
except GeneratorExit:
raise
except Exception as e:
# Map to deserializer error
six.reraise(DeserializationError, DeserializationError(e), sys.exc_info()[2])