Allow to reconstruct a serialized event
import copy
-from uuid import uuid1
+from uuid import UUID, uuid1
+from django.db.models import Model
from django.utils import timezone
from constants import user_system
from event_manager import event_context
-from libs.date_utils import to_timestamp
+from libs.date_utils import to_timestamp, to_datetime
from libs.json_utils import dumps_htmlsafe
@@ -30,7 +31,7 @@ class Attribute(object):
class Event(object):
- __slots__ = ['uuid', 'data', 'datetime', 'instance']
+ __slots__ = ['uuid', 'data', 'datetime', 'instance', 'instance_id', 'instance_contenttype']
event_type = None # The event type should ideally follow subject.action
attributes = ()
@@ -45,14 +46,26 @@ class Event(object):
Attribute(cls.actor_name, is_required=False))
return cls.attributes
- def __init__(self, datetime=None, instance=None, **items):
- self.uuid = uuid1()
+ def __init__(self,
+ uid=None,
+ datetime=None,
+ instance=None,
+ instance_id=None,
+ instance_contenttype=None,
+ event_data=None,
+ **items):
+ self.uuid = UUID(uid) if uid else uuid1()
self.datetime = datetime or timezone.now()
self.instance = instance
+ self.instance_id = instance_id
+ self.instance_contenttype = instance_contenttype
if self.event_type is None:
raise ValueError('Event is missing a type')
+ if event_data:
+ self.data = event_data
+ else:
data = {}
for attr in self.get_event_attributes():
# Check plain attr name
@@ -111,7 +124,7 @@ class Event(object):
return None
return event_context.get_event_action(cls.event_type)
- def serialize(self, dumps=False, include_actor_name=True):
+ def serialize(self, dumps=False, include_actor_name=True, include_instance_info=False):
_data = self.data
if not include_actor_name and self.actor and self.actor_name in _data:
_data = copy.deepcopy(self.data)
@@ -122,6 +135,9 @@ class Event(object):
'type': self.event_type,
'data': _data,
}
+ if include_instance_info:
+ data['instance_id'] = self.instance_id
+ data['instance_contenttype'] = self.instance_contenttype
return dumps_htmlsafe(data) if dumps else data
@classmethod
@@ -136,9 +152,22 @@ class Event(object):
return value
+ @staticmethod
+ def get_instance_info(instance):
+ if isinstance(instance, Model):
+ from django.contrib.contenttypes.models import ContentType
+ return {
+ 'instance_contenttype': ContentType.objects.get_for_model(instance).id,
+ 'instance_id': instance.id
+ }
+ return {}
+
@classmethod
def from_instance(cls, instance, **kwargs):
values = {'instance': instance}
+ if instance:
+ values.update(cls.get_instance_info(instance))
+
for attr in cls.get_event_attributes():
# Convert dot notation
value = kwargs.get(attr.name.replace('.', '_'))
@@ -146,3 +175,13 @@ class Event(object):
value = cls.get_value_from_instance(attr=attr.name, instance=instance)
values[attr.name] = value
return cls(**values)
+
+ @classmethod
+ def from_event_data(cls, event_data):
+ return cls(
+ datetime=to_datetime(event_data.get('timestamp')),
+ uid=event_data.get('uuid'),
+ event_data=event_data.get('data'),
+ instance_id=event_data.get('instance_id'),
+ instance_contenttype=event_data.get('instance_contenttype'),
+ )
