2010-10-14 12 views
6

dado una clase de formulario (en algún lugar profundo en su gigante aplicación Django) ..Monkey parcheando una clase de formulario Django?

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

Y teniendo en cuenta que desea agregar otro campo de esta forma sin ampliación o modificación de la misma clase de formulario, ¿por qué no la hace siguiente trabajo de aproximación?

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

(Mi primera suposición es que el hackery metaclase que utiliza Django se aplica sólo la primera vez que se construye la clase de formulario. Si es así, ¿habría una manera de redeclare la clase de superar esto?)

+0

Seguramente tiene razón. Esta es exactamente la razón por la que no puede agregar fácilmente nuevos campos a una subclase models.Model. –

+0

Con los modelos existe el problema "syncdb" incluso si funcionaba el parche de mono. Pero con las formas de parche de mono podría ser un salvavidas en ciertos momentos en mi humilde opinión. –

Respuesta

7

Algunas definiciones pertinentes ocurren en django/forms/forms.py. Ellos son:

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

get_declared_fields se llama desde DeclarativeFieldsMetaclass y construye una lista con las instancias de campos ordenados por su contador de creación. Luego, antepone los campos de las clases base a esta lista y devuelve el resultado como una instancia OrderedDict con el nombre del campo que sirve 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 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 se está declarando un atributo Media (y ninguna de las clases base hacerlo), entonces sólo devuelve un nuevo Media instancia sin argumentos al constructor y creo que monkeypatching un nuevo campo en debe ser tan simple como insertar manualmente el campo en base_fields.

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

instancia Cada formulario y luego consigue un deepcopy de base_fields que se convierte en form_instance.fields en el método de BaseForm__init__. HTH.

+0

Muchas gracias. Parece funcionar como un encanto. –

+0

+1 El punto a OrderedDict me lleva a SortedDict. No estoy seguro de cuáles son las diferencias, pero ambos funcionaron para mi problema (no sé sobre los OP). Gracias. – jrhorn424

Cuestiones relacionadas