X-Git-Url: http://git.ithinksw.org/philo.git/blobdiff_plain/ed6b9876b7abff0b2dc6266d6f769c319f358a9c..46997a51ed0ceb16ddbac712fbcb552a86cdc9e2:/philo/models/fields/entities.py diff --git a/philo/models/fields/entities.py b/philo/models/fields/entities.py index 6c407d0..3e96d13 100644 --- a/philo/models/fields/entities.py +++ b/philo/models/fields/entities.py @@ -1,29 +1,23 @@ """ -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') @@ -124,6 +118,7 @@ class AttributeFieldDescriptor(object): 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() @@ -135,20 +130,7 @@ def process_attribute_fields(sender, instance, created, **kwargs): 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] @@ -180,6 +162,8 @@ class AttributeField(EntityProxyField): class JSONAttribute(AttributeField): + """Handles an :class:`Attribute` with a :class:`JSONValue`.""" + value_class = JSONValue def __init__(self, field_template=None, **kwargs): @@ -214,6 +198,7 @@ class JSONAttribute(AttributeField): class ForeignKeyAttribute(AttributeField): + """Handles an :class:`Attribute` with a :class:`ForeignKeyValue`.""" value_class = ForeignKeyValue def __init__(self, model, limit_choices_to=None, **kwargs):