"""
-The EntityProxyFields defined in this file can be assigned as fields on
-a subclass of philo.models.Entity. They act like any other model
-fields, but instead of saving their data to the database, they save it
-to attributes related to a model instance. Additionally, a new
-attribute will be created for an instance if and only if the field's
-value has been set. This is relevant i.e. for passthroughs, where the
-value of the field may be defined by some other instance's attributes.
+EntityProxyFields can be assigned as fields on a subclass of philo.models.Entity. They act like any other model fields, but instead of saving their data to the model's table, they save it to attributes related to a model instance. Additionally, a new attribute will be created for an instance if and only if the field's value has been set. This is relevant i.e. for :class:`QuerySetMapper` passthroughs, where even an Attribute with a value of ``None`` must prevent a passthrough.
Example::
class Thing(Entity):
numbers = models.PositiveIntegerField()
-
- class ThingProxy(Thing):
improvised = JSONAttribute(models.BooleanField)
"""
+import datetime
from itertools import tee
+
from django import forms
from django.core.exceptions import FieldError
from django.db import models
from django.db.models.fields import NOT_PROVIDED
from django.utils.text import capfirst
-from philo.signals import entity_class_prepared
+
from philo.models import ManyToManyValue, JSONValue, ForeignKeyValue, Attribute, Entity
-import datetime
+from philo.signals import entity_class_prepared
__all__ = ('JSONAttribute', 'ForeignKeyAttribute', 'ManyToManyAttribute')
def process_attribute_fields(sender, instance, created, **kwargs):
+ """This function is attached to each :class:`Entity` subclass's post_save signal. Any :class:`Attribute`\ s managed by EntityProxyFields which have been removed will be deleted, and any new attributes will be created """
if ATTRIBUTE_REGISTRY in instance.__dict__:
registry = instance.__dict__[ATTRIBUTE_REGISTRY]
instance.attribute_set.filter(key__in=[field.attribute_key for field in registry['removed']]).delete()
attribute = Attribute()
attribute.entity = instance
attribute.key = field.attribute_key
-
- value_class = field.value_class
- if isinstance(attribute.value, value_class):
- value = attribute.value
- else:
- if isinstance(attribute.value, models.Model):
- attribute.value.delete()
- value = value_class()
-
- value.set_value(getattr(instance, field.name, None))
- value.save()
-
- attribute.value = value
- attribute.save()
+ attribute.set_value(value=getattr(instance, field.name, None), value_class=field.value_class)
del instance.__dict__[ATTRIBUTE_REGISTRY]
class JSONAttribute(AttributeField):
+ """Handles an :class:`Attribute` with a :class:`JSONValue`."""
+
value_class = JSONValue
def __init__(self, field_template=None, **kwargs):
class ForeignKeyAttribute(AttributeField):
+ """Handles an :class:`Attribute` with a :class:`ForeignKeyValue`."""
value_class = ForeignKeyValue
def __init__(self, model, limit_choices_to=None, **kwargs):