Does a monkey fix a Django form class?

Given a form class (somewhere in the back of your giant Django app).

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

And if you want to add another field to this form without extending or modifying the form class itself , why does the following approach not work?

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

(My first assumption is that the metaclass hacker that uses Django only applies the first time a form class is created. If so, is it possible to override the class to overcome this?)

+6
python django django-forms monkeypatching
source share
1 answer

Some suitable definitions are found in django/forms/forms.py . It:

  • class BaseForm
  • class Form
  • class DeclarativeFieldsMetaclass
  • def get_declared_fields

get_declared_fields is called from DeclarativeFieldsMetaclass and creates a list with field instances sorted by their creation counter. He then adds the fields from the base classes to this list and returns the result as an OrderedDict instance with the field name serving as keys. DeclarativeFieldsMetaclass then inserts this value into the base_fields attribute and calls type to create the class. Then it passes the class to the media_property function in widgets.py and binds the return value to the media attribute of the new class.

media_property returns a property method that reconstructs the media ads on every access. I feel that this will not be relevant here, but I could be wrong.

Anyway, if you don't declare the media attribute (and none of the base classes), it only returns a fresh instance of media with no arguments to the constructor, and I think that monkeypatching the new on field should be as simple as manually inserting the field into base_fields .

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

Then each instance of the form gets deepcopy of base_fields , which becomes form_instance.fields in the __init__ BaseForm method. NTN.

+7
source share

All Articles