Fixed but of conflicting related names in generic relation

This commit is contained in:
ksamuel 2010-09-10 12:52:18 +00:00
parent c4e0cd715f
commit cd641d2714
4 changed files with 41 additions and 21 deletions

View file

@ -180,9 +180,10 @@ class EavValue(models.Model):
value_int = models.IntegerField(blank=True, null=True)
value_date = models.DateTimeField(blank=True, null=True)
value_bool = models.BooleanField(default=False)
generic_value_id = models.IntegerField(blank=True, null=True)
generic_value_ct = models.ForeignKey(ContentType, blank=True, null=True,
related_name='value_values')
generic_value_id = models.IntegerField(blank=True, null=True)
value_object = generic.GenericForeignKey(ct_field='generic_value_ct',
fk_field='generic_value_id')
@ -202,10 +203,10 @@ class EavValue(models.Model):
"""
Set all the field to none
"""
self.value_bool = False
for field in self._meta.fields:
if field.name.startswith('value_') and field.null == True:
setattr(self, field.name, None)
self.value_bool = False
def _get_value(self):
@ -392,13 +393,4 @@ class EavEntity(object):
def save_handler(sender, *args, **kwargs):
kwargs['instance'].eav.save()
# TODO: remove that, it's just for testing with nose
class Patient(models.Model):
class Meta:
app_label = 'eav_ng'
name = models.CharField(max_length=20)
def __unicode__(self):
return self.name

View file

@ -32,14 +32,15 @@ class EavBasicTests(TestCase):
EavRegistry.unregister(Patient)
def test_attribute_unicode(self):
self.assertEqual(unicode(self.attribute), "City (Text)")
def test_can_create_attribute(self):
EavAttribute.objects.create(datatype=EavAttribute.TYPE_TEXT,
name='My text test', slug='test',
help_text='My help text')
def test_attribute_unicode(self):
self.assertEqual(unicode(self.attribute), "City (Text)")
def test_can_eaventity_children_give_you_all_attributes_by_default(self):
qs = Patient.eav.get_eav_attributes()

View file

@ -1,6 +1,5 @@
from django.db import models
from ..utils import EavRegistry
class Patient(models.Model):
class Meta:
@ -10,3 +9,4 @@ class Patient(models.Model):
def __unicode__(self):
return self.name

View file

@ -1,15 +1,18 @@
from django.contrib.contenttypes import generic
from django.db.utils import DatabaseError
from django.db.models.signals import post_init, post_save, post_delete
from django.db.models.signals import post_init, post_save, post_delete, pre_init
from .managers import EntityManager
from .models import (EavEntity, EavAttribute, EavValue,
get_unique_class_identifier)
#todo : rename this file in registry
class EavConfig(EavEntity):
proxy_field_name = 'eav'
manager_field_name ='objects'
generic_relation_field_name = 'eav_values'
generic_relation_field_related_name = None
@classmethod
def get_eav_attributes(cls):
@ -64,7 +67,8 @@ class EavRegistry(object):
def wrap_config_class(model_cls, config_cls):
"""
Check if the config class is EavConfig, and create a subclass if
it is
it is. We don't want to use eav_config directly since we use the
class as a name space
"""
if config_cls is EavConfig:
return type("%sConfig" % model_cls.__name__, (EavConfig,), {})
@ -84,34 +88,51 @@ class EavRegistry(object):
return
config_cls = EavRegistry.wrap_config_class(model_cls, config_cls)
# we want to call attach and save handler on instance creation and
# saving
post_init.connect(EavRegistry.attach, sender=model_cls)
post_save.connect(EavEntity.save_handler, sender=model_cls)
# todo: rename cache in data
EavRegistry.cache[cls_id] = { 'config_cls': config_cls,
'model_cls': model_cls }
# save the old manager if the attribute name conflict with the new
# one
if hasattr(model_cls, config_cls.manager_field_name):
mgr = getattr(model_cls, config_cls.manager_field_name)
EavRegistry.cache[cls_id]['old_mgr'] = mgr
# set add the config_cls as an attribute of the model
# it will allow to perform some operation directly from this model
setattr(model_cls, config_cls.proxy_field_name, config_cls)
# todo : not useful anymore ?
setattr(getattr(model_cls, config_cls.proxy_field_name),
'get_eav_attributes', config_cls.get_eav_attributes)
# attache the new manager to the model
mgr = EntityManager()
mgr.contribute_to_class(model_cls, config_cls.manager_field_name)
# todo: see with david how to change that
try:
EavEntity.update_attr_cache_for_model(model_cls)
except DatabaseError:
pass
# todo: make that overridable
# attache the generic relation to the model
if config_cls.generic_relation_field_related_name:
rel_name = config_cls.generic_relation_field_related_name
else:
rel_name = model_cls.__name__
gr_name = config_cls.generic_relation_field_name
generic_relation = generic.GenericRelation(EavValue,
object_id_field='entity_id',
content_type_field='entity_ct',
related_name=model_cls.__name__)
related_name=rel_name)
generic_relation.contribute_to_class(model_cls, gr_name)
@ -136,11 +157,17 @@ class EavRegistry(object):
except AttributeError:
pass
# remove remaining reference to the generic relation
gen_rel_field = config_cls.generic_relation_field_name
for field in model_cls._meta.local_many_to_many:
if field.name == gen_rel_field:
model_cls._meta.local_many_to_many.remove(field)
break
try:
delattr(model_cls, config_cls.generic_relation_field_name)
#delattr(EavValue, config_cls.generic_relation_field_name)
delattr(model_cls, gen_rel_field)
except AttributeError:
pass
if 'old_mgr' in cache:
cache['old_mgr'].contribute_to_class(model_cls,