diff --git a/forms.py b/forms.py index e3cf57a..97dcd59 100644 --- a/forms.py +++ b/forms.py @@ -63,7 +63,7 @@ class BaseDynamicEntityForm(ModelForm): defaults = { 'label': attribute.name.capitalize(), - 'required': False, + 'required': attribute.required, 'help_text': attribute.help_text, } diff --git a/models.py b/models.py index 73e9dd9..d522632 100644 --- a/models.py +++ b/models.py @@ -21,7 +21,7 @@ import inspect import re from datetime import datetime -from django.db import models +from django.db import models, IntegrityError from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ from django.contrib.contenttypes.models import ContentType @@ -112,6 +112,8 @@ class Attribute(models.Model): modified = models.DateTimeField(_(u"modified"), auto_now=True) + required = models.BooleanField(_(u"required"), default=False) + def save(self, *args, **kwargs): if not self.slug: @@ -284,6 +286,13 @@ class Entity(object): attribute_value = getattr(self, attribute.slug) attribute.save_value(self.model, attribute_value) + def check_all_required(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}) + def get_values(self): ''' Get all set EAV Value objects for self.model @@ -291,11 +300,9 @@ class Entity(object): return Value.objects.filter(entity_ct=self.ct, entity_id=self.model.pk).select_related() - def get_all_attribute_slugs(self): return self.get_all_attributes().values_list('slug', Flat=True) - def get_attribute_by_slug(self, slug): return self.get_all_attributes().get(slug=slug) @@ -306,8 +313,15 @@ class Entity(object): return iter(self.get_values()) @staticmethod - def save_handler(sender, *args, **kwargs): + def post_save_handler(sender, *args, **kwargs): from .utils import EavRegistry config_cls = EavRegistry.get_config_cls_for_model(sender) entity = getattr(kwargs['instance'], config_cls.eav_attr) entity.save() + + @staticmethod + def pre_save_handler(sender, *args, **kwargs): + 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() diff --git a/utils.py b/utils.py index 3057f0a..0ddbdc3 100644 --- a/utils.py +++ b/utils.py @@ -19,7 +19,7 @@ from django.contrib.contenttypes import generic from django.db.utils import DatabaseError -from django.db.models.signals import post_init, post_save, post_delete, pre_init +from django.db.models.signals import pre_init, post_init, pre_save, post_save from .managers import EntityManager from .models import (Entity, Attribute, Value, get_unique_class_identifier) @@ -101,7 +101,8 @@ class EavRegistry(object): # we want to call attach and save handler on instance creation and # saving post_init.connect(EavRegistry.attach, sender=model_cls) - post_save.connect(Entity.save_handler, sender=model_cls) + post_save.connect(Entity.post_save_handler, sender=model_cls) + pre_save.connect(Entity.pre_save_handler, sender=model_cls) # todo: rename cache in data EavRegistry.cache[cls_id] = { 'config_cls': config_cls, @@ -157,7 +158,8 @@ class EavRegistry(object): manager_only = cache['manager_only'] if not manager_only: post_init.disconnect(EavRegistry.attach, sender=model_cls) - post_save.disconnect(Entity.save_handler, sender=model_cls) + post_save.disconnect(Entity.post_save_handler, sender=model_cls) + pre_save.disconnect(Entity.pre_save_handler, sender=model_cls) try: delattr(model_cls, config_cls.manager_attr)