Added create manager

This commit is contained in:
David Gelvin 2010-09-23 10:38:53 +03:00
parent e30761c96f
commit de37500638
4 changed files with 101 additions and 14 deletions

View file

@ -65,6 +65,7 @@ class BaseDynamicEntityForm(ModelForm):
'label': attribute.name.capitalize(),
'required': attribute.required,
'help_text': attribute.help_text,
'validators': attribute.get_validators()
}
datatype = attribute.datatype

View file

@ -118,3 +118,24 @@ class EntityManager(models.Manager):
@eav_filter
def exclude(self, *args, **kwargs):
return super(EntityManager, self).exclude(*args, **kwargs)
def create(self, *args, **kwargs):
from .utils import EavRegistry
config_cls = EavRegistry.get_config_cls_for_model(self.model)
attributes = config_cls.get_attributes()
prefix = '%s__' % config_cls.eav_attr
new_kwargs = {}
eav_kwargs = {}
for key, value in kwargs.iteritems():
if key.startswith(prefix):
eav_kwargs.update({key[len(prefix):]: value})
else:
new_kwargs.update({key: value})
obj = self.model(**new_kwargs)
obj_eav = getattr(obj, config_cls.eav_attr)
for key, value in eav_kwargs.iteritems():
setattr(obj_eav, key, value)
obj.save()
return obj

View file

@ -21,12 +21,13 @@ import inspect
import re
from datetime import datetime
from django.db import models, IntegrityError
from django.db import models
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from .validators import *
from .fields import EavSlugField, EavDatatypeField
@ -82,7 +83,7 @@ class Attribute(models.Model):
(TYPE_INT, _(u"Integer")),
(TYPE_DATE, _(u"Date")),
(TYPE_BOOLEAN, _(u"True / False")),
(TYPE_OBJECT, _(u"Python Object")),
(TYPE_OBJECT, _(u"Django Object")),
(TYPE_ENUM, _(u"Multiple Choice")),
)
@ -115,6 +116,23 @@ class Attribute(models.Model):
required = models.BooleanField(_(u"required"), default=False)
def get_validators(self):
DATATYPE_VALIDATORS = {
'text': validate_text,
'float': validate_float,
'int': validate_int,
'date': validate_date,
'bool': validate_bool,
'enum': validate_enum,
}
validation_function = DATATYPE_VALIDATORS[self.datatype]
return [validation_function]
def validate_value(self, value):
for validator in self.get_validators():
validator(value)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = EavSlugField.create_slug_from_name(self.name)
@ -188,7 +206,8 @@ class Value(models.Model):
entity_ct = models.ForeignKey(ContentType, related_name='value_entities')
entity_id = models.IntegerField()
entity = generic.GenericForeignKey(ct_field='entity_ct', fk_field='entity_id')
entity = generic.GenericForeignKey(ct_field='entity_ct',
fk_field='entity_id')
value_text = models.TextField(blank=True, null=True)
value_float = models.FloatField(blank=True, null=True)
@ -224,7 +243,7 @@ class Value(models.Model):
{'choice': self.value_enum,
'attribute': self.attribute})
# todo: do it in a faster way (one update)
# TODO: Remove
def _blank(self):
"""
Set all the field to none
@ -256,7 +275,6 @@ class Entity(object):
self.model = instance
self.ct = ContentType.objects.get_for_model(instance)
def __getattr__(self, name):
if not name.startswith('_'):
try:
@ -272,10 +290,15 @@ class Entity(object):
return None
return object.__getattr__(self, name)
'''
@classmethod
def get_all_attributes_for_model(cls, model_cls):
from .utils import EavRegistry
config_cls = EavRegistry.get_config_cls_for_model(model_cls)
return config_cls.get_attributes()
'''
def get_all_attributes(self):
'''
Return all the attributes that are applicable to self.model.
'''
from .utils import EavRegistry
config_cls = EavRegistry.get_config_cls_for_model(self.model.__class__)
return config_cls.get_attributes()
@ -286,12 +309,21 @@ class Entity(object):
attribute_value = getattr(self, attribute.slug)
attribute.save_value(self.model, attribute_value)
def check_all_required(self):
def validate_attributes(self):
for attribute in self.get_all_attributes():
if getattr(self, attribute.slug, None) is None and \
attribute.required:
raise IntegrityError(_(u"%(attr)s EAV field cannot be " \
u"blank") % {'attr':attribute.slug})
value = getattr(self, attribute.slug, None)
if value is None:
if attribute.required:
raise ValidationError(_(u"%(attr)s EAV field cannot " \
u"be blank") % \
{'attr': attribute.slug})
else:
try:
attribute.validate_value(value)
except ValidationError, e:
raise ValidationError(_(u"%(attr)s EAV field %(err)s") % \
{'attr': attribute.slug,
'err': e})
def get_values(self):
'''
@ -324,4 +356,4 @@ class Entity(object):
from .utils import EavRegistry
config_cls = EavRegistry.get_config_cls_for_model(sender)
entity = getattr(kwargs['instance'], config_cls.eav_attr)
entity.check_all_required()
entity.validate_attributes()

33
validators.py Normal file
View file

@ -0,0 +1,33 @@
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
def validate_string(value):
pass
def validate_text(value):
pass
def validate_float(value):
try:
float(value)
except ValueError:
raise ValidationError(_(u"Must be a float"))
def validate_int(value):
try:
int(value)
except ValueError:
raise ValidationError(_(u"Must be an integer"))
def validate_date(value):
#TODO
pass
def validate_bool(value):
pass
def validate_model(value):
pass
def validate_enum(value):
pass