From 4d990a6f5600d82c1be495f215bc6fd680b8e1d8 Mon Sep 17 00:00:00 2001 From: Stephen Burrows Date: Tue, 29 Mar 2011 13:07:13 -0400 Subject: [PATCH] Adjusted 14082 hack again... "fixed" the ModelFormMetaclass.__new__ method and wrote EntityFormMetaclass as if there was no issue. --- admin/base.py | 9 -------- forms/entities.py | 57 +++++++++++++++++++++-------------------------- 2 files changed, 25 insertions(+), 41 deletions(-) diff --git a/admin/base.py b/admin/base.py index b616290..75fa336 100644 --- a/admin/base.py +++ b/admin/base.py @@ -133,15 +133,6 @@ class EntityAdmin(admin.ModelAdmin): # kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical)) return db_field.formfield(**kwargs) - - def get_form(self, request, obj=None, **kwargs): - """ - Ensures that the form's proxy fields are included in its base fields. - This will not be required after http://code.djangoproject.com/ticket/14082 has been resolved - """ - form = super(EntityAdmin, self).get_form(request, obj, **kwargs) - form.base_fields.update(form.proxy_fields) - return form class TreeAdmin(MPTTModelAdmin): diff --git a/forms/entities.py b/forms/entities.py index 43094b9..e781128 100644 --- a/forms/entities.py +++ b/forms/entities.py @@ -42,6 +42,26 @@ def proxy_fields_for_entity_model(entity_model, fields=None, exclude=None, widge return field_dict +# HACK until http://code.djangoproject.com/ticket/14082 is resolved. +_old = ModelFormMetaclass.__new__ +def _new(cls, name, bases, attrs): + if cls == ModelFormMetaclass: + m = attrs.get('__metaclass__', None) + if m is None: + parents = [b for b in bases if issubclass(b, ModelForm)] + for c in parents: + if c.__metaclass__ != ModelFormMetaclass: + m = c.__metaclass__ + break + + if m is not None: + return m(name, bases, attrs) + + return _old(cls, name, bases, attrs) +ModelFormMetaclass.__new__ = staticmethod(_new) +# END HACK + + class EntityFormMetaclass(ModelFormMetaclass): def __new__(cls, name, bases, attrs): try: @@ -55,47 +75,20 @@ class EntityFormMetaclass(ModelFormMetaclass): # Then there's no business trying to use proxy fields. return sup.__new__(cls, name, bases, attrs) - # Preemptively make a meta so we can screen out any proxy fields. - # After http://code.djangoproject.com/ticket/14082 has been resolved, - # perhaps switch to setting proxy fields as "declared"? - _opts = ModelFormOptions(attrs.get('Meta', None)) - - # Make another copy of opts to spoof the proxy fields not being there. + # Fake a declaration of all proxy fields so they'll be handled correctly. opts = ModelFormOptions(attrs.get('Meta', None)) + if opts.model: formfield_callback = attrs.get('formfield_callback', None) proxy_fields = proxy_fields_for_entity_model(opts.model, opts.fields, opts.exclude, opts.widgets, formfield_callback) else: proxy_fields = {} - # Screen out all proxy fields from the meta - opts.fields = list(opts.fields or []) - opts.exclude = list(opts.exclude or []) - - for field in proxy_fields.keys(): - try: - opts.fields.remove(field) - except ValueError: - pass - try: - opts.exclude.remove(field) - except ValueError: - pass - opts.fields = opts.fields or None - opts.exclude = opts.exclude or None - - # Put in the new Meta. - attrs['Meta'] = opts - - new_class = sup.__new__(cls, name, bases, attrs) - - intersections = set(new_class.declared_fields.keys()) & set(proxy_fields.keys()) - for key in intersections: - proxy_fields.pop(key) + new_attrs = proxy_fields.copy() + new_attrs.update(attrs) + new_class = sup.__new__(cls, name, bases, new_attrs) new_class.proxy_fields = proxy_fields - new_class._meta = _opts - new_class.base_fields.update(proxy_fields) return new_class -- 2.20.1