+class ForeignKeyAttribute(AttributeField):
+ descriptor_class = ForeignKeyAttributeDescriptor
+
+ def __init__(self, model, limit_choices_to=None, key=None, **kwargs):
+ super(ForeignKeyAttribute, self).__init__(**kwargs)
+ self.key = key
+ self.model = model
+ if limit_choices_to is None:
+ limit_choices_to = {}
+ self.limit_choices_to = limit_choices_to
+
+ def formfield(self, form_class=forms.ModelChoiceField, **kwargs):
+ defaults = {'required': False, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
+ defaults.update(kwargs)
+ return form_class(self.model._default_manager.complex_filter(self.limit_choices_to), **defaults)
+
+ def value_from_object(self, obj):
+ relobj = super(ForeignKeyAttribute, self).value_from_object(obj).value
+ return getattr(relobj, 'pk', None)
+
+
+class ManyToManyAttribute(AttributeField):
+ descriptor_class = ManyToManyAttributeDescriptor
+ #FIXME: Add __init__ and formfield methods
+
+
+class TemplateField(models.TextField):
+ def __init__(self, allow=None, disallow=None, secure=True, *args, **kwargs):
+ super(TemplateField, self).__init__(*args, **kwargs)
+ self.validators.append(TemplateValidator(allow, disallow, secure))
+
+
+class JSONFormField(forms.Field):
+ def clean(self, value):
+ try:
+ return json.loads(value)
+ except Exception, e:
+ raise ValidationError(u'JSON decode error: %s' % e)
+
+
+class JSONDescriptor(object):