1 from django.db import models
2 from django.db.models import signals
3 from django.core.exceptions import FieldError
4 from philo.models.base import Entity
7 __all__ = ('AttributeField', 'RelationshipField')
10 class AttributeFieldDescriptor(object):
11 def __init__(self, field):
14 def __get__(self, instance, owner):
16 if self.field.key in instance._added_attribute_registry:
17 return instance._added_attribute_registry[self.field.key]
18 if self.field.key in instance._removed_attribute_registry:
21 return instance.attributes[self.field.key]
25 raise AttributeError('The \'%s\' attribute can only be accessed from %s instances.' % (self.field.name, owner.__name__))
27 def __set__(self, instance, value):
28 if self.field.key in instance._removed_attribute_registry:
29 instance._removed_attribute_registry.remove(self.field.key)
30 instance._added_attribute_registry[self.field.key] = value
32 def __delete__(self, instance):
33 if self.field.key in instance._added_attribute_registry:
34 del instance._added_attribute_registry[self.field.key]
35 instance._removed_attribute_registry.append(self.field.key)
38 class AttributeField(object):
39 def __init__(self, key):
42 def actually_contribute_to_class(self, sender, **kwargs):
43 setattr(sender, self.name, AttributeFieldDescriptor(self))
45 def contribute_to_class(self, cls, name):
46 if issubclass(cls, Entity):
48 signals.class_prepared.connect(self.actually_contribute_to_class, sender=cls)
50 raise FieldError('AttributeFields can only be declared on Entity subclasses.')
53 class RelationshipFieldDescriptor(object):
54 def __init__(self, field):
57 def __get__(self, instance, owner):
59 if self.field.key in instance._added_relationship_registry:
60 return instance._added_relationship_registry[self.field.key]
61 if self.field.key in instance._removed_relationship_registry:
64 return instance.relationships[self.field.key]
68 raise AttributeError('The \'%s\' attribute can only be accessed from %s instances.' % (self.field.name, owner.__name__))
70 def __set__(self, instance, value):
71 if isinstance(value, (models.Model, type(None))):
72 if self.field.key in instance._removed_relationship_registry:
73 instance._removed_relationship_registry.remove(self.field.key)
74 instance._added_relationship_registry[self.field.key] = value
76 raise AttributeError('The \'%s\' attribute can only be set using existing Model objects.' % self.field.name)
78 def __delete__(self, instance):
79 if self.field.key in instance._added_relationship_registry:
80 del instance._added_relationship_registry[self.field.key]
81 instance._removed_relationship_registry.append(self.field.key)
84 class RelationshipField(object):
85 def __init__(self, key):
88 def actually_contribute_to_class(self, sender, **kwargs):
89 setattr(sender, self.name, RelationshipFieldDescriptor(self))
91 def contribute_to_class(self, cls, name):
92 if issubclass(cls, Entity):
94 signals.class_prepared.connect(self.actually_contribute_to_class, sender=cls)
96 raise FieldError('RelationshipFields can only be declared on Entity subclasses.')