2011-07-14 16 views
10

मेरे पास एक मॉडल है और मैंने ModelForm का उपयोग कर मॉडल से एक फॉर्म बनाया है। अब, मैं फॉर्म को दो पृष्ठों में फैलाना चाहता हूं। उदाहरण के लिए, पहले तीन फ़ील्ड पहले पृष्ठ पर दिखाई देंगे, फिर उपयोगकर्ता अगले क्लिक करता है और अंतिम तीन फ़ील्ड दूसरे पृष्ठ पर दिखाई देते हैं। फिर वह सबमिट पर क्लिक करता है और उपयोगकर्ता द्वारा सबमिट किया गया डेटा डेटाबेस में जोड़ा जाता है।क्या आप django में मॉडल प्रपत्रों के लिए फॉर्म विज़ार्ड का उपयोग कर सकते हैं?

मैंने फ़ॉर्म विज़ार्ड के लिए दस्तावेज़ों पर एक नज़र डाली और ऐसा लगता है कि यह मॉडल रूपों के लिए भी काम करेगा? क्या कोई इसकी पुष्टि कर सकता है?

और यदि ऐसा होता है, तो कोई WizardView कक्षा बनाने की प्रक्रिया को समझा सकता है।

यह उदाहरण दस्तावेज़ों में दिया गया है और मुझे समझ में नहीं आता कि दूसरे दो पैरामीटर क्या हैं। क्या फॉर्म_लिस्ट केवल फॉर्म ऑब्जेक्ट्स की एक सूची है जिसे आपने अपने फॉर्म क्लास के आधार पर तुरंत चालू कर दिया है? और **kwargs क्या है?

class ContactWizard(SessionWizardView): 
    def done(self, form_list, **kwargs): 
     do_something_with_the_form_data(form_list) 
     return HttpResponseRedirect('/page-to-redirect-to-when-done/') 

आपकी मदद के लिए अग्रिम धन्यवाद!

उत्तर

6

फॉर्म विज़ार्ड Django 1.4 में बनाया जा रहा है, इसलिए इसके बारे में जाने का एक अच्छा तरीका है। यह वही करना चाहिए जो आप चाहते हैं, लेकिन आपको कुछ बदलावों की आवश्यकता हो सकती है।

पल में done() में kwargs के बारे में चिंता मत करो - आप उन्हें जरूरत के लिए नहीं जा रहे हैं। से urls.py

urlpatterns = patterns('', 
    (r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2])), 
) 

[ContactForm1, ContactForm2]form_list रूप done() को दे दिया जाएगा -

form_list रूपों है कि आप अपने कदम के लिए उपयोग करना चाहते हैं की सूची है।

आपको क्या करना होगा ModelForm अलग-अलग रूपों में तोड़ना है। ऐसा करने का सबसे आसान तरीका (यदि आप अपने मॉडल को कई रूपों पर चाहते हैं) ModelForm का उपयोग नहीं करना है, बल्कि अपना स्वयं का फॉर्म बनाएं।

from django import forms 

class ContactForm1(forms.Form): 
    subject = forms.CharField(max_length=100) 
    sender = forms.EmailField() 

class ContactForm2(forms.Form): 
    message = forms.CharField(widget=forms.Textarea) 

एक बार अपने फ़ॉर्म देखें अपने मॉडल के कुछ भागों को प्रतिबिंबित, बस docs में वर्णित है और एक समारोह है कि प्रपत्र डेटा से अपने मॉडल पूर्ण करता do_something_with_the_form_data(form_list) सेट के रूप में views और patterns बना कर किसी ऐसे कार्य करता है: यह बहुत आसान है बचाना।

आप ModelForm का उपयोग कर सकते हैं, लेकिन केवल अगर आप फॉर्म विज़ार्ड के लिए प्रत्येक चरण के लिए उपयोग करने के लिए इसे अलग-अलग रूपों का उत्पादन करने के लिए राजी कर सकते हैं - यह मुश्किल हिस्सा होगा।

+7

आप 'उपयोग करने के लिए ModelForm' चुनते हैं, तो आप' fields' या 'का उपयोग कर सकते हैं: इस दृष्टिकोण का बड़ा लाभ यह है कि यह हमेशा हर कदम के लिए एक नया उदाहरण बनाने की बजाय AModel का एक ही उदाहरण का उपयोग करता है प्रत्येक चरण के लिए दृश्यमान फ़ील्ड को नियंत्रित करने के लिए 'को शामिल नहीं करता है। – gjb

19

हम एक FormWizard का उपयोग कर एक अलग चरण में प्रत्येक क्षेत्र सेट करना चाहते हैं अपने मॉडल दो क्षेत्रों

class AModel(Model): 
    fieldA = CharField() 
    fieldB = CharField() 

है कहो।इसलिए हम दो ModelForm रों, प्रत्येक दिखाते हुए एक क्षेत्र बनाने के लिए:

class Form1(ModelForm): 
    class Meta: 
     model = AModel 
     fields = ('fieldA',) 

class Form2(ModelForm): 
    class Meta: 
     model = AModel 
     fields = ('fieldB',) 

हम अपने प्रपत्र विज़ार्ड AWizard कहते हैं; url.py प्रविष्टि की तरह

url(r'^$', AWizard.as_view([ Form1, Form2 ])), 

कुछ दिखना चाहिए AWizard के कार्यान्वयन में हम यकीन है कि सभी रूपों एक उदाहरण है, जो हम तो डेटाबेस के लिए बचाने के लिए अपनी डेटा लिखने बनाने की जरूरत है:

class AWizard(SessionWizardView): 
    instance = None 

    def get_form_instance(self, step): 
     if self.instance is None: 
      self.instance = AModel() 
     return self.instance 

    def done(self, form_list, **kwargs): 
     self.instance.save() 

ध्यान दें कि हम विधि get_form_instance को ओवरराइड करते हैं। यह विधि मॉडल उदाहरण को फॉर्म से जोड़ती है।

आप सोच सकते हैं (मैंने किया), यह विधि पहले अनुरोध (विज़ार्ड का पहला चरण) के लिए एक उदाहरण बनाता है, और फिर सभी चरणों के लिए उसी उदाहरण का उपयोग करता रहता है।

असल में, यह थोड़ा और जटिल है। प्रत्येक अनुरोध के लिए AWizard का एक नया उदाहरण बनाया गया है, जो बदले में एक नया AModel उदाहरण बनाता है। इसलिए, चरणों के साथ शुरू करने के लिए एक उदाहरण साझा नहीं करते हैं।

अंतिम फॉर्म सबमिट होने पर जादू होता है। इस बिंदु पर सभी रूपों को पुन: सत्यापित किया जाता है, प्रत्येक प्रपत्र get_form_instance पर कॉल करता है और वे एक AModel उदाहरण पॉपुलटिंग को समाप्त करते हैं।

उस उदाहरण को done में सहेजा गया है। (बचत

class AWizard(SessionWizardView): 
    def dispatch(self, request, *args, **kwargs): 
     self.instance = AModel() 
     return super(ApplyWizard, self).dispatch(request, *args, **kwargs) 

    def get_form_instance(self, step): 
     return self.instance 

    def done(self, form_list, **kwargs): 
     self.instance.save() 
     return HttpResponseRedirect(reverse(thanks)) 
2

दृश्य @wuerg द्वारा प्रस्तावित मेरे लिए काम नहीं किया, मैं यह करने के लिए किया था हर कदम के बाद)।

class AWizard(SessionWizardView): 
    instance = AModel() 

    def dispatch(self, request, *args, **kwargs): 
     return super(AWizard, self).dispatch(request, *args, **kwargs) 

    def get_form_instance(self, step): 
     return self.instance 

    def done(self, form_list, **kwargs): 
     self.save_model() 
     return render_to_response('done.html') 
+0

मैं अपना फॉर्म 1 बटन के रेडियो बटन चयन पर प्रदर्शित करना चाहता हूं..मैं यह कैसे कर सकता हूं? क्या आप मुझे मार्गदर्शन कर सकते हैं? –

0

मैं अपने USECASE में काम करने के @wuerg और @madmen के समाधान को बदलना पड़ा मॉडल:

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