diff options
Diffstat (limited to 'django-simple-history/simple_history/models.py')
| -rw-r--r-- | django-simple-history/simple_history/models.py | 169 | 
1 files changed, 0 insertions, 169 deletions
| diff --git a/django-simple-history/simple_history/models.py b/django-simple-history/simple_history/models.py deleted file mode 100644 index 06054ba34..000000000 --- a/django-simple-history/simple_history/models.py +++ /dev/null @@ -1,169 +0,0 @@ -import copy -from django.db import models -from django.contrib import admin -from django.contrib.auth.models import User -from django.utils import importlib -from manager import HistoryDescriptor - - -class HistoricalRecords(object): -    def contribute_to_class(self, cls, name): -        self.manager_name = name -        self.module = cls.__module__ -        models.signals.class_prepared.connect(self.finalize, sender=cls) - -        def save_without_historical_record(self, *args, **kwargs): -            """Caution! Make sure you know what you're doing before you use this method.""" -            self.skip_history_when_saving = True -            ret = self.save(*args, **kwargs) -            del self.skip_history_when_saving -            return ret -        setattr(cls, 'save_without_historical_record', save_without_historical_record) - -    def finalize(self, sender, **kwargs): -        history_model = self.create_history_model(sender) -        module = importlib.import_module(self.module) -        setattr(module, history_model.__name__, history_model) - -        # The HistoricalRecords object will be discarded, -        # so the signal handlers can't use weak references. -        models.signals.post_save.connect(self.post_save, sender=sender, -                                         weak=False) -        models.signals.post_delete.connect(self.post_delete, sender=sender, -                                           weak=False) - -        descriptor = HistoryDescriptor(history_model) -        setattr(sender, self.manager_name, descriptor) -        sender._meta.simple_history_manager_attribute = self.manager_name - -    def create_history_model(self, model): -        """ -        Creates a historical model to associate with the model provided. -        """ -        attrs = {'__module__': self.module} - -        fields = self.copy_fields(model) -        attrs.update(fields) -        attrs.update(self.get_extra_fields(model, fields)) -        attrs.update(Meta=type('Meta', (), self.get_meta_options(model))) -        name = 'Historical%s' % model._meta.object_name -        return type(name, (models.Model,), attrs) - -    def copy_fields(self, model): -        """ -        Creates copies of the model's original fields, returning -        a dictionary mapping field name to copied field object. -        """ -        fields = {} - -        for field in model._meta.fields: -            field = copy.copy(field) -            fk = None - -            if isinstance(field, models.AutoField): -                # The historical model gets its own AutoField, so any -                # existing one must be replaced with an IntegerField. -                field.__class__ = models.IntegerField - -            if isinstance(field, models.ForeignKey): -                field.__class__ = models.IntegerField -                #ughhhh. open to suggestions here -                try: -                    field.rel = None -                except: -                    pass -                try: -                    field.related = None -                except: -                    pass -                try: -                    field.related_query_name = None -                except: -                    pass -                field.null = True -                field.blank = True -                fk = True -            else: -                fk = False - -            # The historical instance should not change creation/modification timestamps. -            field.auto_now = False -            field.auto_now_add = False - -            if field.primary_key or field.unique: -                # Unique fields can no longer be guaranteed unique, -                # but they should still be indexed for faster lookups. -                field.primary_key = False -                field._unique = False -                field.db_index = True -                field.serialize = True -            if fk: -                field.name = field.name + "_id" -            fields[field.name] = field - -        return fields - -    def get_extra_fields(self, model, fields): -        """ -        Returns a dictionary of fields that will be added to the historical -        record model, in addition to the ones returned by copy_fields below. -        """ -        @models.permalink -        def revert_url(self): -            opts = model._meta -            return ('%s:%s_%s_simple_history' % -                    (admin.site.name, opts.app_label, opts.module_name), -                    [getattr(self, opts.pk.attname), self.history_id]) -        def get_instance(self): -            return model(**dict([(k, getattr(self, k)) for k in fields])) - -        return { -            'history_id': models.AutoField(primary_key=True), -            'history_date': models.DateTimeField(auto_now_add=True), -            'history_user': models.ForeignKey(User, null=True), -            'history_type': models.CharField(max_length=1, choices=( -                ('+', 'Created'), -                ('~', 'Changed'), -                ('-', 'Deleted'), -            )), -            'history_object': HistoricalObjectDescriptor(model), -            'instance': property(get_instance), -            'revert_url': revert_url, -            '__unicode__': lambda self: u'%s as of %s' % (self.history_object, -                                                          self.history_date) -        } - -    def get_meta_options(self, model): -        """ -        Returns a dictionary of fields that will be added to -        the Meta inner class of the historical record model. -        """ -        return { -            'ordering': ('-history_date', '-history_id'), -        } - -    def post_save(self, instance, created, **kwargs): -        if not created and hasattr(instance, 'skip_history_when_saving'): -            return -        if not kwargs.get('raw', False): -            self.create_historical_record(instance, created and '+' or '~') - -    def post_delete(self, instance, **kwargs): -        self.create_historical_record(instance, '-') - -    def create_historical_record(self, instance, type): -        history_user = getattr(instance, '_history_user', None) -        manager = getattr(instance, self.manager_name) -        attrs = {} -        for field in instance._meta.fields: -            attrs[field.attname] = getattr(instance, field.attname) -        manager.create(history_type=type, history_user=history_user, **attrs) - - -class HistoricalObjectDescriptor(object): -    def __init__(self, model): -        self.model = model - -    def __get__(self, instance, owner): -        values = (getattr(instance, f.attname) for f in self.model._meta.fields) -        return self.model(*values) | 
