+class ForeignKeyValue(models.Model):
+ content_type = models.ForeignKey(ContentType, related_name='foreign_key_value_set', limit_choices_to=value_content_type_limiter, verbose_name='Value type', null=True, blank=True)
+ object_id = models.PositiveIntegerField(verbose_name='Value ID', null=True, blank=True)
+ value = generic.GenericForeignKey()
+
+ def __unicode__(self):
+ return unicode(self.value)
+
+ def value_formfield(self, form_class=forms.ModelChoiceField, **kwargs):
+ if self.content_type is None:
+ return None
+ kwargs.update({'initial': self.object_id, 'required': False})
+ return form_class(self.content_type.model_class()._default_manager.all(), **kwargs)
+
+ class Meta:
+ app_label = 'philo'
+
+
+class ManyToManyValue(models.Model):
+ content_type = models.ForeignKey(ContentType, related_name='many_to_many_value_set', limit_choices_to=value_content_type_limiter, verbose_name='Value type', null=True, blank=True)
+ object_ids = models.CommaSeparatedIntegerField(max_length=300, verbose_name='Value IDs', null=True, blank=True)
+
+ def get_value(self):
+ return self.content_type.model_class()._default_manager.filter(id__in=self.object_ids)
+
+ def set_value(self, value):
+ if not isinstance(value, models.query.QuerySet):
+ raise TypeError("Value must be a QuerySet.")
+ self.content_type = ContentType.objects.get_for_model(value.model)
+ self.object_ids = ','.join(value.values_list('id', flat=True))
+
+ value = property(get_value, set_value)
+
+ def __unicode__(self):
+ return unicode(self.value)
+
+ class Meta:
+ app_label = 'philo'
+
+
+attribute_value_limiter = ContentTypeRegistryLimiter()
+attribute_value_limiter.register_class(JSONValue)
+attribute_value_limiter.register_class(ForeignKeyValue)
+attribute_value_limiter.register_class(ManyToManyValue)
+
+
+class Attribute(models.Model):
+ entity_content_type = models.ForeignKey(ContentType, related_name='attribute_entity_set', verbose_name='Entity type')