Add registration via metaclass (#23)

Example:

    class SomeModel(metaclass=EAVModelMeta):
        pass
This commit is contained in:
MajekX 2018-07-27 16:00:28 +02:00 committed by Iwo Herka
parent 99254cd578
commit f35ceaed22
8 changed files with 80 additions and 3 deletions

3
.gitignore vendored
View file

@ -123,3 +123,6 @@ venv.bak/
*~
# Auto-generated tag files
tags
## Mac
.DS_Store

View file

@ -5,7 +5,8 @@ This module defines the four concrete, non-abstract models:
* :class:`EnumValue`
* :class:`EnumGroup`
Along with the :class:`Entity` helper class.
Along with the :class:`Entity` helper class and :class:`EAVModelMeta`
optional metaclass for each eav model class.
"""
from copy import copy
@ -14,12 +15,14 @@ from django.contrib.contenttypes import fields as generic
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models.base import ModelBase
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from .exceptions import IllegalAssignmentException
from .fields import EavDatatypeField, EavSlugField
from .validators import *
from . import register
class EnumValue(models.Model):
@ -615,3 +618,10 @@ class Entity(object):
for i in m.eav: print(i)
"""
return iter(self.get_values())
class EAVModelMeta(ModelBase):
def __new__(cls, name, bases, namespace, **kwds):
result = super(EAVModelMeta, cls).__new__(cls, name, bases, dict(namespace))
register(result)
return result

View file

@ -251,7 +251,7 @@ def expand_eav_filter(model_cls, key, value):
else:
sub_key = '__'.join(fields[1:])
key, value = expand_eav_filter(field.model, sub_key, value)
return '{}__{}'.format(ields[0], key), value
return '{}__{}'.format(fields[0], key), value
class EavQuerySet(QuerySet):

View file

@ -1,6 +1,7 @@
from django.core.exceptions import ValidationError
from django.test import TestCase
import sys
import eav
from eav.exceptions import IllegalAssignmentException
from eav.models import Attribute, Value
@ -8,6 +9,10 @@ from eav.registry import EavConfig
from .models import Encounter, Patient
if sys.version_info[0] > 2:
from .metaclass_models3 import RegisterTestModel
else:
from .metaclass_models2 import RegisterTestModel
class Attributes(TestCase):
def setUp(self):
@ -47,17 +52,25 @@ class Attributes(TestCase):
def test_setting_attributes(self):
p = Patient.objects.create(name='Jon')
e = Encounter.objects.create(patient=p, num=1)
p.eav.age = 3
p.eav.height = 2.3
p.save()
e.eav_field.age = 4
e.save()
self.assertEqual(Value.objects.count(), 3)
t = RegisterTestModel.objects.create(name="test")
t.eav.age = 6
t.eav.height = 10
t.save()
p = Patient.objects.get(name='Jon')
self.assertEqual(p.eav.age, 3)
self.assertEqual(p.eav.height, 2.3)
e = Encounter.objects.get(num=1)
self.assertEqual(e.eav_field.age, 4)
t = RegisterTestModel.objects.get(name="test")
self.assertEqual(t.eav.age, 6)
self.assertEqual(t.eav.height, 10)
def test_illegal_assignemnt(self):
class EncounterEavConfig(EavConfig):

View file

@ -0,0 +1,18 @@
from django.db import models
from eav.models import EAVModelMeta
class ExampleMetaclassModel(models.Model):
__metaclass__ = EAVModelMeta
name = models.CharField(max_length=12)
def __unicode__(self):
return self.name
class RegisterTestModel(models.Model):
__metaclass__ = EAVModelMeta
name = models.CharField(max_length=12)
def __unicode__(self):
return self.name

View file

@ -0,0 +1,16 @@
from django.db import models
from eav.models import EAVModelMeta
class ExampleMetaclassModel(models.Model, metaclass=EAVModelMeta):
name = models.CharField(max_length=12)
def __str__(self):
return self.name
class RegisterTestModel(models.Model, metaclass=EAVModelMeta):
name = models.CharField(max_length=12)
def __str__(self):
return self.name

View file

@ -1,10 +1,16 @@
from django.test import TestCase
import sys
import eav
from eav.registry import EavConfig
from .models import Encounter, ExampleModel, Patient
if sys.version_info[0] > 2:
from .metaclass_models3 import ExampleMetaclassModel
else:
from .metaclass_models2 import ExampleMetaclassModel
class RegistryTests(TestCase):
def setUp(self):
@ -55,6 +61,11 @@ class RegistryTests(TestCase):
self.assertEqual(ExampleModel._eav_config_cls.manager_attr, 'objects')
self.assertEqual(ExampleModel._eav_config_cls.eav_attr, 'eav')
def test_register_via_metaclass_with_defaults(self):
self.assertTrue(hasattr(ExampleMetaclassModel, '_eav_config_cls'))
self.assertEqual(ExampleMetaclassModel._eav_config_cls.manager_attr, 'objects')
self.assertEqual(ExampleMetaclassModel._eav_config_cls.eav_attr, 'eav')
def test_unregistering(self):
old_mgr = Patient.objects
eav.register(Patient)
@ -69,6 +80,11 @@ class RegistryTests(TestCase):
eav.unregister(ExampleModel)
self.assertFalse(ExampleModel.objects.__class__.__name__ == 'EntityManager')
def test_unregistering_via_metaclass(self):
self.assertTrue(ExampleMetaclassModel.objects.__class__.__name__ == 'EntityManager')
eav.unregister(ExampleMetaclassModel)
self.assertFalse(ExampleMetaclassModel.objects.__class__.__name__ == 'EntityManager')
def test_unregistering_unregistered_model_proceeds_silently(self):
eav.unregister(Patient)
@ -80,4 +96,4 @@ class RegistryTests(TestCase):
with self.assertRaises(ValueError):
@eav.decorators.register_eav()
class Foo(object):
pass
pass

View file

@ -12,4 +12,5 @@ deps =
django111: Django >=1.11, <2.0
django20: Django >= 2.0, <2.1
djangotip: Django
commands = ./runtests