2010-10-14 84 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