diff options
Diffstat (limited to 'django-simple-history/simple_history/manager.py')
| -rwxr-xr-x | django-simple-history/simple_history/manager.py | 75 | 
1 files changed, 75 insertions, 0 deletions
| diff --git a/django-simple-history/simple_history/manager.py b/django-simple-history/simple_history/manager.py new file mode 100755 index 000000000..923b310eb --- /dev/null +++ b/django-simple-history/simple_history/manager.py @@ -0,0 +1,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:]) | 
