mirror of
https://github.com/jazzband/django-eav2.git
synced 2026-05-01 12:14:56 +00:00
Add ability to assign enum values as strings (#46)
* Add ability to assign enum values as strings * Remove unreachable code (enum validation now fails earlier) * Enable filtering by enum value
This commit is contained in:
parent
27cf385f58
commit
e857819fce
7 changed files with 44 additions and 25 deletions
|
|
@ -210,9 +210,10 @@ foreign-keys:
|
|||
# Of course, you can mix them with regular queries:
|
||||
Part.objects.filter(name='Cog', eav__height=7.8)
|
||||
|
||||
# Querying enums looks as follows:
|
||||
# Querying enums works either by enum instance or by it's text representation as follows:
|
||||
yes = EnumValue.objects.get(name='Yes')
|
||||
Part.objects.filter(eav__is_available=yes)
|
||||
Part.objects.filter(eav__is_available=yes) # via EnumValue
|
||||
Part.objects.filter(eav__is_available='yes) # via EnumValue's value
|
||||
|
||||
You can use ``Q`` expressions too:
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,17 @@ from django.db.models.base import ModelBase
|
|||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .validators import (
|
||||
validate_text,
|
||||
validate_float,
|
||||
validate_int,
|
||||
validate_date,
|
||||
validate_bool,
|
||||
validate_object,
|
||||
validate_enum
|
||||
)
|
||||
from .exceptions import IllegalAssignmentException
|
||||
from .fields import EavDatatypeField, EavSlugField
|
||||
from .validators import *
|
||||
from . import register
|
||||
|
||||
|
||||
|
|
@ -245,7 +253,9 @@ class Attribute(models.Model):
|
|||
validator(value)
|
||||
|
||||
if self.datatype == self.TYPE_ENUM:
|
||||
if value not in self.enum_group.values.all():
|
||||
if isinstance(value, EnumValue):
|
||||
value = value.value
|
||||
if not self.enum_group.values.filter(value=value).exists():
|
||||
raise ValidationError(
|
||||
_('%(val)s is not a valid choice for %(attr)s')
|
||||
% dict(val = value, attr = self)
|
||||
|
|
@ -405,18 +415,6 @@ class Value(models.Model):
|
|||
self.full_clean()
|
||||
super(Value, self).save(*args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Raises ``ValidationError`` if this value's attribute is *TYPE_ENUM*
|
||||
and value_enum is not a valid choice for this value's attribute.
|
||||
"""
|
||||
if self.attribute.datatype == Attribute.TYPE_ENUM and self.value_enum:
|
||||
if self.value_enum not in self.attribute.enum_group.values.all():
|
||||
raise ValidationError(
|
||||
_('%(enum)s is not a valid choice for %(attr)s')
|
||||
% dict(enum = self.value_enum, attr = self.attribute)
|
||||
)
|
||||
|
||||
def _get_value(self):
|
||||
"""
|
||||
Return the python object this value is holding
|
||||
|
|
@ -530,6 +528,8 @@ class Entity(object):
|
|||
for attribute in self.get_all_attributes():
|
||||
if self._hasattr(attribute.slug):
|
||||
attribute_value = self._getattr(attribute.slug)
|
||||
if attribute.datatype == Attribute.TYPE_ENUM and not isinstance(attribute_value, EnumValue):
|
||||
attribute_value = EnumValue.objects.get(value=attribute_value)
|
||||
attribute.save_value(self.instance, attribute_value)
|
||||
|
||||
def validate_attributes(self):
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ from django.db.models import Case, IntegerField, Q, When
|
|||
from django.db.models.query import QuerySet
|
||||
from django.db.utils import NotSupportedError
|
||||
|
||||
from .models import Attribute, Value
|
||||
from .models import Attribute, Value, EnumValue
|
||||
|
||||
|
||||
def is_eav_and_leaf(expr, gr_name):
|
||||
|
|
@ -234,7 +234,10 @@ def expand_eav_filter(model_cls, key, value):
|
|||
gr_name = config_cls.generic_relation_attr
|
||||
datatype = Attribute.objects.get(slug=slug).datatype
|
||||
|
||||
lookup = '__%s' % fields[2] if len(fields) > 2 else ''
|
||||
if datatype == Attribute.TYPE_ENUM and not isinstance(value, EnumValue):
|
||||
lookup = '__value__{}'.format(fields[2]) if len(fields) > 2 else '__value'
|
||||
else:
|
||||
lookup = '__{}'.format(fields[2]) if len(fields) > 2 else ''
|
||||
kwargs = {
|
||||
'value_{}{}'.format(datatype, lookup): value,
|
||||
'attribute__slug': slug
|
||||
|
|
|
|||
|
|
@ -81,8 +81,5 @@ def validate_enum(value):
|
|||
"""
|
||||
from .models import EnumValue
|
||||
|
||||
if not isinstance(value, EnumValue):
|
||||
raise ValidationError(_(u"Must be an EnumValue model object instance"))
|
||||
|
||||
if not value.pk:
|
||||
if isinstance(value, EnumValue) and not value.pk:
|
||||
raise ValidationError(_(u"EnumValue has not been saved yet"))
|
||||
|
|
|
|||
|
|
@ -155,8 +155,6 @@ class DataValidation(TestCase):
|
|||
self.assertRaises(ValidationError, p.save)
|
||||
p.eav.fever = object
|
||||
self.assertRaises(ValidationError, p.save)
|
||||
p.eav.fever = 'yes'
|
||||
self.assertRaises(ValidationError, p.save)
|
||||
p.eav.fever = green
|
||||
self.assertRaises(ValidationError, p.save)
|
||||
p.eav.fever = EnumValue(value='yes')
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from eav.models import EnumGroup, Attribute, Value
|
||||
from eav.models import EnumGroup, Attribute, Value, EnumValue
|
||||
|
||||
import eav
|
||||
from .models import Patient
|
||||
|
|
@ -25,3 +25,17 @@ class MiscModels(TestCase):
|
|||
p.eav.age = None
|
||||
p.save()
|
||||
self.assertEqual(Value.objects.count(), 0)
|
||||
|
||||
def test_string_enum_value_assignment(self):
|
||||
yes = EnumValue.objects.create(value='yes')
|
||||
no = EnumValue.objects.create(value='no')
|
||||
ynu = EnumGroup.objects.create(name='Yes / No / Unknown')
|
||||
ynu.values.add(yes)
|
||||
ynu.values.add(no)
|
||||
Attribute.objects.create(name='is_patient', datatype=Attribute.TYPE_ENUM, enum_group=ynu)
|
||||
eav.register(Patient)
|
||||
p = Patient.objects.create(name='Joe')
|
||||
p.eav.is_patient = 'yes'
|
||||
p.save()
|
||||
p = Patient.objects.get(name='Joe') # get from DB again
|
||||
self.assertEqual(p.eav.is_patient, yes)
|
||||
|
|
|
|||
|
|
@ -94,6 +94,12 @@ class Queries(TestCase):
|
|||
p = Patient.objects.filter(q2 & q1)
|
||||
self.assertEqual(p.count(), 2)
|
||||
|
||||
# Anne
|
||||
q1 = Q(eav__city__contains='Y') & Q(eav__fever='no')
|
||||
q2 = Q(eav__age=3)
|
||||
p = Patient.objects.filter(q1 & q2)
|
||||
self.assertEqual(p.count(), 1)
|
||||
|
||||
# Anne
|
||||
q1 = Q(eav__city__contains='Y') & Q(eav__fever=self.no)
|
||||
q2 = Q(eav__age=3)
|
||||
|
|
|
|||
Loading…
Reference in a new issue