Added support for DateTime information being stored in a JSONAttribute. Switched...
authorStephen Burrows <stephen.r.burrows@gmail.com>
Tue, 25 Jan 2011 16:15:06 +0000 (11:15 -0500)
committerStephen Burrows <stephen.r.burrows@gmail.com>
Tue, 25 Jan 2011 21:43:40 +0000 (16:43 -0500)
contrib/cowell/fields.py
contrib/cowell/forms.py

index c5db56d..176554e 100644 (file)
@@ -23,6 +23,7 @@ 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
 
 
 __all__ = ('JSONAttribute', 'ForeignKeyAttribute', 'ManyToManyAttribute')
@@ -68,6 +69,11 @@ class EntityProxyField(object):
                this field's initial value."""
                return getattr(obj, self.name)
        
+       def get_storage_value(self, value):
+               """Final conversion of `value` before it gets stored on an Entity instance.
+               This step is performed by the ProxyFieldForm."""
+               return value
+       
        def has_default(self):
                return self.default is not NOT_PROVIDED
        
@@ -158,7 +164,6 @@ class AttributeField(EntityProxyField):
                if not hasattr(opts, '_has_attribute_fields'):
                        opts._has_attribute_fields = True
                        models.signals.post_save.connect(process_attribute_fields, sender=sender)
-               
        
        def contribute_to_class(self, cls, name):
                if self.attribute_key is None:
@@ -167,7 +172,7 @@ class AttributeField(EntityProxyField):
        
        def validate_value(self, value):
                "Confirm that the value is valid or raise an appropriate error."
-               raise NotImplementedError("validate_value must be implemented by AttributeField subclasses.")
+               pass
        
        @property
        def value_class(self):
@@ -183,9 +188,6 @@ class JSONAttribute(AttributeField):
                        field_template = models.CharField(max_length=255)
                self.field_template = field_template
        
-       def validate_value(self, value):
-               pass
-       
        def formfield(self, **kwargs):
                defaults = {
                        'required': False,
@@ -196,6 +198,19 @@ class JSONAttribute(AttributeField):
                        defaults['initial'] = self.default
                defaults.update(kwargs)
                return self.field_template.formfield(**defaults)
+       
+       def value_from_object(self, obj):
+               value = super(JSONAttribute, self).value_from_object(obj)
+               if isinstance(self.field_template, (models.DateField, models.DateTimeField)):
+                       value = self.field_template.to_python(value)
+               return value
+       
+       def get_storage_value(self, value):
+               if isinstance(value, datetime.datetime):
+                       return value.strftime("%Y-%m-%d %H:%M:%S")
+               if isinstance(value, datetime.date):
+                       return value.strftime("%Y-%m-%d")
+               return value
 
 
 class ForeignKeyAttribute(AttributeField):
@@ -203,18 +218,18 @@ class ForeignKeyAttribute(AttributeField):
        
        def __init__(self, model, limit_choices_to=None, **kwargs):
                super(ForeignKeyAttribute, self).__init__(**kwargs)
-               self.model = model
+               self.to = model
                if limit_choices_to is None:
                        limit_choices_to = {}
                self.limit_choices_to = limit_choices_to
        
        def validate_value(self, value):
-               if value is not None and not isinstance(value, self.model) :
-                       raise TypeError("The '%s' attribute can only be set to an instance of %s or None." % (self.name, self.model.__name__))
+               if value is not None and not isinstance(value, self.to) :
+                       raise TypeError("The '%s' attribute can only be set to an instance of %s or None." % (self.name, self.to.__name__))
        
        def formfield(self, form_class=forms.ModelChoiceField, **kwargs):
                defaults = {
-                       'queryset': self.model._default_manager.complex_filter(self.limit_choices_to)
+                       'queryset': self.to._default_manager.complex_filter(self.limit_choices_to)
                }
                defaults.update(kwargs)
                return super(ForeignKeyAttribute, self).formfield(form_class=form_class, **defaults)
@@ -223,22 +238,17 @@ class ForeignKeyAttribute(AttributeField):
                relobj = super(ForeignKeyAttribute, self).value_from_object(obj)
                return getattr(relobj, 'pk', None)
        
-       @property
-       def to(self):
-               """Spoof being a rel from a ForeignKey."""
-               return self.model
-       
        def get_related_field(self):
-               """Again, spoof being a rel from a ForeignKey."""
-               return self.model._meta.pk
+               """Spoof being a rel from a ForeignKey."""
+               return self.to._meta.pk
 
 
 class ManyToManyAttribute(ForeignKeyAttribute):
        value_class = ManyToManyValue
        
        def validate_value(self, value):
-               if not isinstance(value, models.query.QuerySet) or value.model != self.model:
-                       raise TypeError("The '%s' attribute can only be set to a %s QuerySet." % (self.name, self.model.__name__))
+               if not isinstance(value, models.query.QuerySet) or value.model != self.to:
+                       raise TypeError("The '%s' attribute can only be set to a %s QuerySet." % (self.name, self.to.__name__))
        
        def formfield(self, form_class=forms.ModelMultipleChoiceField, **kwargs):
                return super(ManyToManyAttribute, self).formfield(form_class=form_class, **kwargs)
index 0b5a0c6..aa8b6ca 100644 (file)
@@ -90,7 +90,7 @@ class ProxyFieldForm(ProxyFieldFormBase): # Would inherit from ModelForm directl
                                continue
                        if self._meta.exclude and f.name in self._meta.exclude:
                                continue
-                       setattr(instance, f.attname, cleaned_data[f.name])
+                       setattr(instance, f.attname, f.get_storage_value(cleaned_data[f.name]))
                
                if commit:
                        instance.save()