mirror of
https://github.com/jazzband/django-eav2.git
synced 2026-03-17 06:50:24 +00:00
Many fixes and filtering
This commit is contained in:
parent
8185f43458
commit
4a889b48bf
4 changed files with 63 additions and 34 deletions
18
managers.py
18
managers.py
|
|
@ -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)
|
||||
|
|
|
|||
73
models.py
73
models.py
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in a new issue