From 78da723fd43fdaa44f588c0b642ca8f8348b4be0 Mon Sep 17 00:00:00 2001 From: Stephen Burrows Date: Thu, 21 Oct 2010 15:05:07 -0400 Subject: [PATCH] Added support for 'editable' to ProxyFields. Tweaked AttributeFieldDescriptor base class to not raise an AttributeError on access. This allows the descriptor to be detected by Django admin validation, allowing the proxy fields to be used (for example) in a ModelAdmin's readonly_fields and list_display fields. This may address the remaining issues in feature #16. --- forms.py | 6 ++++++ models/fields.py | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/forms.py b/forms.py index 48e1d7f..a1785fb 100644 --- a/forms.py +++ b/forms.py @@ -21,6 +21,8 @@ def proxy_fields_for_entity_model(entity_model, fields=None, exclude=None, widge ignored = [] opts = entity_model._entity_meta for f in opts.proxy_fields: + if not f.editable: + continue if fields and not f.name in fields: continue if exclude and f.name in exclude: @@ -86,8 +88,12 @@ class EntityForm(EntityFormBase): # Would inherit from ModelForm directly if it instance = super(EntityForm, self).save(commit=False) for f in instance._entity_meta.proxy_fields: + if not f.editable or not f.name in cleaned_data: + continue if self._meta.fields and f.name not in self._meta.fields: continue + if self._meta.exclude and f.name in self._meta.exclude: + continue setattr(instance, f.attname, cleaned_data[f.name]) if commit: diff --git a/models/fields.py b/models/fields.py index cff8ff8..85c5583 100644 --- a/models/fields.py +++ b/models/fields.py @@ -14,12 +14,13 @@ __all__ = ('JSONAttribute', 'ForeignKeyAttribute', 'ManyToManyAttribute') class EntityProxyField(object): descriptor_class = None - def __init__(self, verbose_name=None, help_text=None, default=NOT_PROVIDED, *args, **kwargs): + def __init__(self, verbose_name=None, help_text=None, default=NOT_PROVIDED, editable=True, *args, **kwargs): if self.descriptor_class is None: raise NotImplementedError('EntityProxyField subclasses must specify a descriptor_class.') self.verbose_name = verbose_name self.help_text = help_text self.default = default + self.editable = editable def actually_contribute_to_class(self, sender, **kwargs): sender._entity_meta.add_proxy_field(self) @@ -61,7 +62,7 @@ class AttributeFieldDescriptor(object): except KeyError: return None else: - raise AttributeError('The \'%s\' attribute can only be accessed from %s instances.' % (self.field.name, owner.__name__)) + return None def __set__(self, instance, value): raise NotImplementedError('AttributeFieldDescriptor subclasses must implement a __set__ method.') -- 2.20.1