django-eav2/utils.py
2010-09-07 08:33:42 +00:00

92 lines
2.8 KiB
Python

from django.db.models.signals import post_init, pre_save
from .managers import EntityManager
from .models import EavEntity, EavAttribute
class EavConfig(object):
@classmethod
def get_eav_attributes(cls):
"""
By default, all attributes apply to an entity,
unless otherwise specified.
"""
return EavAttribute.objects.all()
class EavRegistry(object):
"""
Tools to add eav features to models
"""
field_cache = {}
@staticmethod
def attach(sender, *args, **kwargs):
"""
Attache EAV toolkit to an instance after init.
"""
instance = kwargs['instance']
cls = instance.__class__
proxy_name = EavRegistry.field_cache[cls.__name__]['proxy']
setattr(instance, proxy_name, EavEntity(instance))
@staticmethod
def register(model_cls, admin_cls=EavConfig, eav_proxy_field='eav',
eav_manager_field='objects'):
"""
Inject eav features into the given model and attach a signal
listener to it for setup.
"""
if model_cls.__name__ in EavRegistry.field_cache:
return
post_init.connect(EavRegistry.attach, sender=model_cls)
pre_save.connect(EavEntity.pre_save_handler, sender=model_cls)
EavRegistry.field_cache[model_cls.__name__] = {
'proxy': eav_proxy_field,
'mgr': eav_manager_field}
if hasattr(model_cls, eav_manager_field):
mgr = getattr(model_cls, eav_manager_field)
EavRegistry.field_cache[model_cls.__name__]['old_mgr'] = mgr
setattr(model_cls, eav_proxy_field, EavEntity)
setattr(getattr(model_cls, eav_proxy_field),
'get_eav_attributes', admin_cls.get_eav_attributes)
mgr = EntityManager()
mgr.contribute_to_class(model_cls, eav_manager_field)
@staticmethod
def unregister(model_cls):
"""
Inject eav features into the given model and attach a signal
listener to it for setup.
"""
if not model_cls.__name__ in EavRegistry.field_cache:
return
cache = EavRegistry.field_cache[model_cls.__name__]
post_init.disconnect(EavRegistry.attach, sender=model_cls)
pre_save.disconnect(EavEntity.pre_save_handler, sender=model_cls)
proxy_name = cache['proxy']
mgr_name = cache['mgr']
try:
delattr(model_cls, mgr_name)
except AttributeError:
pass
if 'old_mgr' in cache:
cache['old_mgr'].contribute_to_class(model_cls, mgr_name)
try:
delattr(model_cls, proxy_name)
except AttributeError:
pass
EavRegistry.field_cache.pop(model_cls.__name__)