1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
|
from django.db import models
class HistoryDescriptor(object):
def __init__(self, model):
self.model = model
def __get__(self, instance, owner):
if instance is None:
return HistoryManager(self.model)
return HistoryManager(self.model, instance)
class HistoryManager(models.Manager):
def __init__(self, model, instance=None):
super(HistoryManager, self).__init__()
self.model = model
self.instance = instance
def get_query_set(self):
if self.instance is None:
return super(HistoryManager, self).get_query_set()
if isinstance(self.instance._meta.pk, models.OneToOneField):
filter = {self.instance._meta.pk.name + "_id": self.instance.pk}
else:
filter = {self.instance._meta.pk.name: self.instance.pk}
return super(HistoryManager, self).get_query_set().filter(**filter)
def most_recent(self):
"""
Returns the most recent copy of the instance available in the history.
"""
if not self.instance:
raise TypeError("Can't use most_recent() without a %s instance." %
self.instance._meta.object_name)
tmp = []
for field in self.instance._meta.fields:
if isinstance(field, models.ForeignKey):
tmp.append(field.name + "_id")
else:
tmp.append(field.name)
fields = tuple(tmp)
try:
values = self.values_list(*fields)[0]
except IndexError:
raise self.instance.DoesNotExist("%s has no historical record." %
self.instance._meta.object_name)
return self.instance.__class__(*values)
def as_of(self, date):
"""
Returns an instance of the original model with all the attributes set
according to what was present on the object on the date provided.
"""
if not self.instance:
raise TypeError("Can't use as_of() without a %s instance." %
self.instance._meta.object_name)
tmp = []
for field in self.instance._meta.fields:
if isinstance(field, models.ForeignKey):
tmp.append(field.name + "_id")
else:
tmp.append(field.name)
fields = tuple(tmp)
qs = self.filter(history_date__lte=date)
try:
values = qs.values_list('history_type', *fields)[0]
except IndexError:
raise self.instance.DoesNotExist("%s had not yet been created." %
self.instance._meta.object_name)
if values[0] == '-':
raise self.instance.DoesNotExist("%s had already been deleted." %
self.instance._meta.object_name)
return self.instance.__class__(*values[1:])
|