''' Created on Apr 10, 2012 @author: leifj ''' from django.db import models from django.db.models.fields import DateTimeField from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes import generic from django_extensions.db.fields import UUIDField from django.dispatch.dispatcher import receiver from django.db.models.signals import post_save, pre_delete from django.core.exceptions import ObjectDoesNotExist from django.db.models.base import ModelBase class NotAModel(Exception): pass class RecursiveRegistration(Exception): pass class UninitializedObject(Exception): pass class Resource(models.Model): uuid = UUIDField(unique=True) content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey('content_type', 'object_id') lastupdated = DateTimeField(auto_now=True) timecreated = DateTimeField(auto_now_add=True) def __unicode__(self): return self.uuid def object_for_uuid(uuid): try: r = Resource.objects.get(uuid=uuid) return r.content_object except ObjectDoesNotExist: return None def uuid_for_object(o): if not o.id: raise UninitializedObject("Can't obtain uuid for non-persisted objects") typ = ContentType.objects.get_for_model(o) r,cr = Resource.objects.get_or_create(object_id=o.id,content_type=typ) return r.uuid def add_resource(o): typ = ContentType.objects.get_for_model(o) r,cr = Resource.objects.get_or_create(object_id=o.id,content_type=typ) return r.uuid def delete_resource(o): typ = ContentType.objects.get_for_model(o) try: r = Resource.objects.get(object_id=o.id,content_type=typ) r.delete() except ObjectDoesNotExist: pass class ResourceClassRegistry(): def __init__(self): self._registry = [] def register(self,model,addField=True): if not isinstance(model,ModelBase): raise NotAModel('%s does not appear to be a model!' % model) if not model in self._registry: if addField: setattr(model,'uuid',property(lambda x: uuid_for_object(x))) self._registry.append(model) resources = ResourceClassRegistry() def register(model): resources.register(model) @receiver(post_save) def auto_create_resource(sender,**kwargs): if sender in resources._registry and kwargs['created']: add_resource(kwargs['instance']) @receiver(pre_delete) def auto_delete_resource(sender,**kwargs): if sender in resources._registry: delete_resource(kwargs['instance'])