Many fixes and filtering

This commit is contained in:
David Gelvin 2010-09-08 12:10:47 +00:00
parent 8185f43458
commit 4a889b48bf
4 changed files with 63 additions and 34 deletions

View file

@ -1,4 +1,7 @@
import re
from django.db import models
from .models import EavEntity
class EntityManager(models.Manager):
def filter(self, *args, **kwargs):
@ -9,11 +12,9 @@ class EntityManager(models.Manager):
return qs
def _filter_by_lookup(self, qs, lookup, value):
eav_entity = self._get_eav_entity()
slugs = eav_entity.get_all_attribute_slugs()
cache = eav_entity.get_attr_cache()
slugs = EavEntity.get_all_attribute_slugs_for_model(self.model)
fields = self.model._meta.get_all_field_names()
attributes = eav_entity.get_all_attributes()
attributes = EavEntity.get_all_attributes_for_model(self.model)
config_cls = self._get_config_cls()
eav_prefix = config_cls.proxy_field_name
@ -22,14 +23,14 @@ class EntityManager(models.Manager):
if not lookup.startswith("%s__" % eav_prefix):
return {lookup: value}
lookup = lookup.lstrip("%s__" % eav_prefix)
lookup = re.sub(r'^%s__' % eav_prefix, '', lookup)
# Sublookup will be None if there is no __ in the lookup
name, sublookup = (lookup.split('__', 1) + [None])[:2]
if name in slugs:
# EAV attribute (Attr instance linked to entity)
attribute = eav_entity.get_attribute_by_slug(name)
attribute = EavEntity.get_attribute_by_slug_for_model(self.model , name)
return self._filter_by_simple_schema(qs, lookup, sublookup, value, attribute)
else:
raise NameError('Cannot filter items by attributes: unknown '
@ -51,8 +52,3 @@ class EntityManager(models.Manager):
def _get_config_cls(self):
from .utils import EavRegistry
return EavRegistry.get_config_cls_for_model(self.model)
def _get_eav_entity(self):
cls = self._get_config_cls()
eav_entity_name = cls.proxy_field_name
return getattr(self.model, eav_entity_name)

View file

@ -83,7 +83,11 @@ class EavAttribute(models.Model):
self.slug = EavSlugField.create_slug_from_name(self.name)
self.full_clean()
super(EavAttribute, self).save(*args, **kwargs)
EavEntity.update_all_caches()
def delete(self, *args, **kwargs):
EavEntity.update_all_caches()
super(EavAttribute, self).delete(*args, **kwargs)
def add_label(self, label):
label, created = EavAttributeLabel.objects.get_or_create(name=label)
@ -170,11 +174,6 @@ class EavValue(models.Model):
'''
#class Meta:
# we can't a TextField on mysql with a unique constraint
#unique_together = ('entity_ct', 'entity_id', 'attribute',
# 'value_text', 'value_float', 'value_date',
# 'value_bool')
entity_ct = models.ForeignKey(ContentType, related_name='value_entities')
entity_id = models.IntegerField()
entity = generic.GenericForeignKey(ct_field='entity_ct', fk_field='entity_id')
@ -190,6 +189,9 @@ class EavValue(models.Model):
value_object = generic.GenericForeignKey(ct_field='generic_value_ct',
fk_field='generic_value_id')
created = models.DateTimeField(_(u"created"), default=datetime.now)
modified = models.DateTimeField(_(u"modified"), auto_now=True)
attribute = models.ForeignKey(EavAttribute)
def save(self, *args, **kwargs):
@ -258,7 +260,15 @@ class EavEntity(object):
cache['slug_mapping'] = dict((s.slug, s) for s in cache['attributes'])
return cache
@classmethod
def update_all_caches(cls):
"""
Update all caches of registered entities.
"""
from .utils import EavRegistry
for entity in EavRegistry.cache.itervalues():
cls.update_attr_cache_for_model(entity['model_cls'])
@classmethod
def flush_attr_cache_for_model(cls, model_cls):
"""
@ -299,38 +309,63 @@ class EavEntity(object):
attribute_value = getattr(self, attribute.slug)
attribute.save_value(self.model, attribute_value)
def get_all_attributes(self):
@classmethod
def get_all_attributes_for_model(cls, model_cls):
"""
Return the current cache or if it doesn't exists, update it
and returns it.
"""
cache = self.get_attr_cache()
cache = cls.get_attr_cache_for_model(model_cls)
if not cache:
cache = self.update_attr_cache()
cache = EavEntity.update_attr_cache_for_model(model_cls)
return cache['attributes']
def get_all_attributes(self):
m_cls = self.__class__
return self.__class__.get_all_attributes_for_model(m_cls)
def get_values(self):
return EavValue.objects.filter(entity_ct=self.ct,
entity_id=self.model.pk).select_related()
@classmethod
def get_all_attribute_slugs_for_model(cls, model_cls):
"""
Returns all attributes slugs for the entity
class linked to the passed model.
"""
cache = cls.get_attr_cache_for_model(model_cls)
if not cache:
cache = EavEntity.update_attr_cache_for_model(model_cls)
return cache['slug_mapping']
def get_all_attribute_slugs(self):
"""
Returns all attributes slugs for the entity
class linked to the current instance.
"""
cache = self.get_attr_cache()
m_cls = self.model.__class__
return self.__class__.get_all_attribute_slugs_for_model(m_cls)
@classmethod
def get_attribute_by_slug_for_model(cls, model_cls, slug):
"""
Returns all attributes slugs for the entity
class linked to the passed model.
"""
cache = cls.get_attr_cache_for_model(model_cls)
if not cache:
cache = self.update_attr_cache()
return cache['slug_mapping']
cache = EavEntity.update_attr_cache_for_model(model_cls)
if slug in cache['slug_mapping']:
return cache['slug_mapping'][slug]
def get_attribute_by_slug(self, slug):
"""
Returns an attribute object knowing the slug for the entity
class linked to the current instance.
"""
return self.get_all_attribute_slugs().get(slug, None)
m_cls = self.model.__class__
return self.__class__.get_attribute_by_slug_for_model(m_cls, slug)
def get_attribute_by_id(self, attribute_id):
"""

View file

@ -124,9 +124,7 @@ class EavBasicTests(TestCase):
def test_eavregistry_ataches_and_detaches_eav_attribute(self):
EavRegistry.unregister(Patient)
print "hello"
p = Patient()
print "hello"
self.assertFalse(hasattr(p, 'eav'))
EavRegistry.register(Patient)

View file

@ -173,8 +173,8 @@ class EavSetterAndGetterTests(TestCase):
p.eav.country = 'USA'
p.save()
p = Patient.objects.get(pk=p.pk)
self.assertFalse(p.eav.city)
self.assertFalse(p.eav.city, 'Paris')
self.assertEqual(p.eav.country, 'USA')
p = Patient()