Files
mayan-edms/apps/trash/models.py

129 lines
4.3 KiB
Python

import datetime
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.db import transaction, DatabaseError
from common.managers import CustomizableQuerySetManager
from common.querysets import CustomizableQuerySet
from common.models import TranslatableLabelMixin
class TrashCanManager(models.Manager):
@transaction.commit_on_success
def make_trashable(self, full_model_name, label=None):
app_name, model_name = full_model_name.split('.')
model = models.get_model(app_name, model_name)
if model:
try:
trash_can, created = self.model.objects.get_or_create(name=app_name)
except DatabaseError:
transaction.rollback()
else:
trash_can.label = label or model._meta.verbose_name_plural
old_manager = getattr(model, '_default_manager')
model.add_to_class('objects', CustomizableQuerySet.as_manager(TrashableQuerySetManager))
model._default_manager = model.objects
model.add_to_class('trash_passthru', old_manager)
old_delete_method = model.delete
model.delete = new_delete_method(trash_can, old_delete_method)
class TrashCan(TranslatableLabelMixin, models.Model):
translatables = ['label']
trash_can_labels = {}
name = models.CharField(max_length=32, verbose_name=_(u'name'), unique=True)
objects = TrashCanManager()
def __unicode__(self):
return unicode(self.label) or self.name
def put(self, obj):
# TODO: check if obj is trashable model
obj.delete()
@property
def items(self):
return self.trashcanitem_set
def empty(self):
self.items.all().delete()
def save(self, *args, **kwargs):
label = getattr(self, 'label', None)
if label:
TrashCan.trash_can_labels[self.name] = label
return super(TrashCan, self).save(*args, **kwargs)
class Meta:
verbose_name = _(u'trash can')
verbose_name_plural = _(u'trash cans')
class TrashCanItemManager(models.Manager):
def is_in_trash(self, obj):
content_type = ContentType.objects.get_for_model(obj)
try:
self.model.objects.get(content_type=content_type, object_id=obj.id)
except self.model.DoesNotExist:
return False
else:
return True
def ids(self):
return [trash_item.object_id for trash_item in self.model.objects.all()]
class TrashCanItem(models.Model):
trash_can = models.ForeignKey(TrashCan, verbose_name=_(u'trash can'))
trashed_at = models.DateTimeField(verbose_name=_(u'trashed at'), editable=False)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
objects = TrashCanItemManager()
def __unicode__(self):
return unicode(self.content_object)
def restore(self):
self.delete()
def purge(self):
self.content_object.delete(trash=False)
self.delete()
def save(self, *args, **kwargs):
if not self.pk:
self.trashed_at=datetime.datetime.now()
return super(TrashCanItem, self).save(*args, **kwargs)
class Meta:
verbose_name = _(u'trash can item')
verbose_name_plural = _(u'trash can items')
unique_together = ('trash_can', 'content_type', 'object_id')
class TrashableQuerySetManager(CustomizableQuerySetManager):
def get_query_set(self):
return super(TrashableQuerySetManager, self).get_query_set().exclude(pk__in=TrashCanItem.objects.ids())
def new_delete_method(trash_can, old_delete_method):
def delete(self, *args, **kwargs):
trash = kwargs.pop('trash', True)
if trash==False:
return old_delete_method(self, *args, **kwargs)
else:
#trashed_item = TrashedItem.objects.create(trash_can=trash_can, content_object=self, trashed_at=datetime.datetime.now())
trashed_item = trash_can.items.create(trash_can=trash_can, content_object=self)
return delete