class ManyToManyValue(AttributeValue):
+ # TODO: Change object_ids to object_pks.
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)
return form_class(self.content_type.model_class()._default_manager.all(), **kwargs)
def apply_data(self, cleaned_data):
- self.value = cleaned_data.get('value', None)
+ if 'value' in cleaned_data and cleaned_data['value'] is not None:
+ self.value = cleaned_data['value']
+ else:
+ self.content_type = cleaned_data.get('content_type', None)
+ # If there is no value set in the cleaned data, clear the stored value.
+ self.object_ids = ""
class Meta:
app_label = 'philo'
key = models.CharField(max_length=255)
- def get_value_class(self, value):
- if isinstance(value, models.query.QuerySet):
- return ManyToManyValue
- elif isinstance(value, models.Model) or (value is None and self.value_content_type.model_class() is ForeignKeyValue):
- return ForeignKeyValue
- else:
- return JSONValue
-
- def set_value(self, value):
- # is this useful? The best way of doing it?
- value_class = self.get_value_class(value)
-
- if self.value is None or value_class != self.value_content_type.model_class():
- if self.value is not None:
- self.value.delete()
- new_value = value_class()
- new_value.value = value
- new_value.save()
- self.value = new_value
- else:
- self.value.value = value
- self.value.save()
-
def __unicode__(self):
return u'"%s": %s' % (self.key, self.value)
self.attribute_set.filter(key__exact=key).delete()
del self._removed_attribute_registry[:]
- for key, value in self._added_attribute_registry.items():
+ for field, value in self._added_attribute_registry.items():
try:
- attribute = self.attribute_set.get(key__exact=key)
+ attribute = self.attribute_set.get(key__exact=field.key)
except Attribute.DoesNotExist:
attribute = Attribute()
attribute.entity = self
- attribute.key = key
- attribute.set_value(value)
+ attribute.key = field.key
+
+ field.set_attribute_value(attribute, value)
attribute.save()
self._added_attribute_registry.clear()
def __get__(self, instance, owner):
if instance:
- if self.field.key in instance._added_attribute_registry:
- return instance._added_attribute_registry[self.field.key]
- if self.field.key in instance._removed_attribute_registry:
+ if self.field in instance._added_attribute_registry:
+ return instance._added_attribute_registry[self.field]
+ if self.field in instance._removed_attribute_registry:
return None
try:
return instance.attributes[self.field.key]
raise NotImplementedError('AttributeFieldDescriptor subclasses must implement a __set__ method.')
def __delete__(self, instance):
- if self.field.key in instance._added_attribute_registry:
- del instance._added_attribute_registry[self.field.key]
- instance._removed_attribute_registry.append(self.field.key)
+ if self.field in instance._added_attribute_registry:
+ del instance._added_attribute_registry[self.field]
+ instance._removed_attribute_registry.append(self.field)
class JSONAttributeDescriptor(AttributeFieldDescriptor):
def __set__(self, instance, value):
- if self.field.key in instance._removed_attribute_registry:
- instance._removed_attribute_registry.remove(self.field.key)
- instance._added_attribute_registry[self.field.key] = value
+ if self.field in instance._removed_attribute_registry:
+ instance._removed_attribute_registry.remove(self.field)
+ instance._added_attribute_registry[self.field] = value
class ForeignKeyAttributeDescriptor(AttributeFieldDescriptor):
def __set__(self, instance, value):
if isinstance(value, (models.Model, type(None))):
- if self.field.key in instance._removed_attribute_registry:
- instance._removed_attribute_registry.remove(self.field.key)
- instance._added_attribute_registry[self.field.key] = value
+ if self.field in instance._removed_attribute_registry:
+ instance._removed_attribute_registry.remove(self.field)
+ instance._added_attribute_registry[self.field] = value
else:
raise AttributeError('The \'%s\' attribute can only be set using existing Model objects.' % self.field.name)
class ManyToManyAttributeDescriptor(AttributeFieldDescriptor):
def __set__(self, instance, value):
if isinstance(value, models.QuerySet):
- if self.field.key in instance._removed_attribute_registry:
- instance._removed_attribute_registry.remove(self.field.key)
- instance._added_attribute_registry[self.field.key] = value
+ if self.field in instance._removed_attribute_registry:
+ instance._removed_attribute_registry.remove(self.field)
+ instance._added_attribute_registry[self.field] = value
else:
raise AttributeError('The \'%s\' attribute can only be set to a QuerySet.' % self.field.name)
super(AttributeField, self).contribute_to_class(cls, name)
if self.key is None:
self.key = name
+
+ def set_attribute_value(self, attribute, value, value_class):
+ if not isinstance(attribute.value, value_class):
+ if isinstance(attribute.value, models.Model):
+ attribute.value.delete()
+ new_value = value_class()
+ else:
+ new_value = attribute.value
+ new_value.value = value
+ new_value.save()
+ attribute.value = new_value
class JSONAttribute(AttributeField):
return self.field_template.formfield(**defaults)
def value_from_object(self, obj):
- return getattr(obj, self.attname).value
+ try:
+ return getattr(obj, self.attname).value
+ except AttributeError:
+ return None
+
+ def set_attribute_value(self, attribute, value, value_class=None):
+ if value_class is None:
+ from philo.models.base import JSONValue
+ value_class = JSONValue
+ super(JSONAttribute, self).set_attribute_value(attribute, value, value_class)
class ForeignKeyAttribute(AttributeField):
return form_class(self.model._default_manager.complex_filter(self.limit_choices_to), **defaults)
def value_from_object(self, obj):
- relobj = super(ForeignKeyAttribute, self).value_from_object(obj).value
+ try:
+ relobj = super(ForeignKeyAttribute, self).value_from_object(obj).value
+ except AttributeError:
+ return None
return getattr(relobj, 'pk', None)
+
+ def set_attribute_value(self, attribute, value, value_class=None):
+ if value_class is None:
+ from philo.models.base import ForeignKeyValue
+ value_class = ForeignKeyValue
+ super(ForeignKeyAttribute, self).set_attribute_value(attribute, value, value_class)
-class ManyToManyAttribute(AttributeField):
+class ManyToManyAttribute(ForeignKeyAttribute):
descriptor_class = ManyToManyAttributeDescriptor
- #FIXME: Add __init__ and formfield methods
+
+ def formfield(self, form_class=forms.ModelMultipleChoiceField, **kwargs):
+ return super(ManyToManyAttribute, self).formfield(form_class, **kwargs)
+
+ def set_attribute_value(self, attribute, value, value_class=None):
+ if value_class is None:
+ from philo.models.base import ManyToManyValue
+ value_class = ManyToManyValue
+ super(ManyToManyAttribute, self).set_attribute_value(attribute, value, value_class)
class TemplateField(models.TextField):