2010-10-14 86 views
6

给定一个窗体类(深某处的巨型Django应用程序).​​.猴子修补Django表单类吗?

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

并考虑要将其他字段添加到该表格没有延长或修改窗体类本身,为什么不以下的方法工作?

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

(我的第一个猜测是,该Django使用元类两轮牛车只适用于第一次的窗体类的构造。如果是的话,会有一个方式重新声明来克服这一类?)

+0

你几乎肯定是对的。这正是您无法轻松地将新字段添加到models.Model子类的原因。 – 2010-10-14 06:13:37

+0

即使猴子补丁工作,模型也存在“syncdb”的问题。但随着形式猴子补丁可能是在某些时候恕我直言救生员。 – 2010-10-14 06:24:29

回答

7

一些相关的定义发生在django/forms/forms.py。它们是:

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

get_declared_fieldsDeclarativeFieldsMetaclass调用并构建由他们的创作计数器排序字段实例列表。然后,它将从基类的字段预先添加到此列表中,并将结果作为OrderedDict实例,字段名称用作键。 DeclarativeFieldsMetaclass然后将该值粘贴在属性base_fields中,并调用type来构造该类。然后它将该类传递给widgets.py中的media_property函数,并将返回值附加到新类的media属性。

media_property返回一个属性方法,该方法重建每个访问上的媒体声明。我的感觉是,它不会在这里相关,但我可能是错的。无论如何,如果你没有声明Media属性(并且没有基类),那么它只返回一个新的Media实例,没有参数给构造函数,我认为monkeypatching一个新的字段应该是就像手动将字段插入base_fields一样简单。

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

每个表单实例然后得到base_fields在的BaseForm__init__方法变得form_instance.fieldsdeepcopy。 HTH。

+0

非常感谢。似乎像魅力一样工作。 – 2010-10-17 19:41:59

+0

+1 OrderedDict指向SortedDict。不知道有什么区别,但他们都适合我的问题(不知道OP的)。谢谢。 – jrhorn424 2012-03-05 01:29:00