¿Mono parcheando una clase de forma Django?

Dada una clase de formulario (en algún lugar profundo de tu aplicación gigante de Django) …

class ContactForm(forms.Form): name = ... surname = ... 

Y teniendo en cuenta que desea agregar otro campo a este formulario sin extender o modificar la clase de formulario , ¿por qué no funciona el siguiente enfoque?

 ContactForm.another_field = forms.CharField(...) 

(Mi primera suposición es que la piratería de metaclase que usa Django se aplica solo la primera vez que se construye la clase de formulario. Si es así, ¿habría una manera de redeclarar la clase para superar esto?)

Algunas definiciones pertinentes aparecen en django/forms/forms.py . Son:

  1. class BaseForm
  2. class Form
  3. class DeclarativeFieldsMetaclass
  4. def get_declared_fields

Se llama a get_declared_fields desde DeclarativeFieldsMetaclass y construye una lista con las instancias de campo ordenadas por su contador de creación. Luego anula los campos de las clases base a esta lista y devuelve el resultado como una instancia de OrderedDict con el nombre del campo como claves. DeclarativeFieldsMetaclass luego pega este valor en el atributo base_fields y llama al type para construir la clase. Luego pasa la clase a la función media_property en widgets.py y adjunta el valor de retorno al atributo de media en la nueva clase.

media_property devuelve un método de propiedad que reconstruye las declaraciones de medios en cada acceso. Mi sensación es que no será relevante aquí, pero podría estar equivocado.

En cualquier caso, si no está declarando un atributo de Media (y ninguna de las clases base lo hace), entonces solo devuelve una instancia de Media nueva sin argumentos al constructor y creo que hacer un mono de plot en un nuevo campo debería ser tan simple como manualmente Insertando el campo en base_fields .

 ContactForm.another_field = forms.CharField(...) ContactForm.base_fields['another_field'] = ContactForm.another_field 

Cada instancia de formulario luego obtiene una deepcopy de los base_fields que se convierten en form_instance.fields en el método BaseForm de BaseForm . HTH.