2010-10-14 16 views
6

एक रूप वर्ग को देखते हुए (अपने विशाल Django अनुप्रयोग में कहीं गहरे) ..बंदर एक Django फॉर्म वर्ग पैचिंग?

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

और विस्तार या प्रपत्र वर्ग ही संशोधित बिना पर विचार आप इस फार्म के लिए एक और क्षेत्र में जोड़ना चाहते हैं, क्यों नहीं करता है निम्नलिखित दृष्टिकोण काम करते हैं?

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

(मेरा पहला अनुमान है कि metaclass hackery कि Django का उपयोग करता है केवल पहली बार प्रपत्र वर्ग का निर्माण किया है पर लागू होता है है। यदि हां, तो वहाँ? वर्ग इस पर काबू पाने के लिए redeclare के लिए एक रास्ता होगा)

+0

आप लगभग निश्चित रूप से सही हैं। यही कारण है कि आप आसानी से मॉडल में नए फ़ील्ड नहीं जोड़ सकते हैं। मॉडल उपclass। –

+0

मॉडल के साथ बंदर पैचिंग काम करने के बावजूद "syncdb" परेशानी है। लेकिन फॉर्म बंदर पैचिंग के साथ कुछ समय आईएमएचओ में एक जीवन बचतकर्ता हो सकता है। –

उत्तर

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 पर कॉल करता है। इसके बाद यह वर्ग media_property फ़ंक्शन को widgets.py में पास करता है और नए वर्ग पर 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.fields हो जाता है की एक deepcopy हो जाता है। HTH।

+0

बहुत बहुत धन्यवाद। एक आकर्षण की तरह काम करने के लिए लगता है। –

+0

+1 ऑर्डर्ड डिक्ट की ओर इशारा करते हुए मुझे सॉर्टेड डिक्ट की ओर ले जाता है। निश्चित नहीं है कि अंतर क्या हैं, लेकिन वे दोनों मेरे मुद्दे के लिए काम करते हैं (ओपी के बारे में नहीं जानते)। धन्यवाद। – jrhorn424

संबंधित मुद्दे