+class JSONAttributeDescriptor(AttributeFieldDescriptor):
+ def __set__(self, instance, 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 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 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)
+
+
+class AttributeField(EntityProxyField):
+ def contribute_to_class(self, cls, 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):
+ descriptor_class = JSONAttributeDescriptor
+
+ def __init__(self, field_template=None, key=None, **kwargs):
+ super(AttributeField, self).__init__(**kwargs)