2009-07-18 11 views
7

एक दृश्य में एक फार्म के प्रसंस्करण के लिए suggested पैटर्न मेरे लिए बहुत जटिल और गैर सूखी लगता है:django प्रपत्र प्रसंस्करण बॉयलरप्लेट के लिए वैकल्पिक?

def contact(request): 
    if request.method == 'POST': # If the form has been submitted... 
     form = ContactForm(request.POST) # A form bound to the POST data 
     if form.is_valid(): # All validation rules pass 
      # Process the data in form.cleaned_data 
      # ... 
      return HttpResponseRedirect('/thanks/') # Redirect after POST 
    else: 
     form = ContactForm() # An unbound form 

    return render_to_response('contact.html', { 
     'form': form, 
    }) 

सशर्त, का एक बहुत कुछ है यही कारण है, यह ContactForm() निर्माण को दोहराता है, और पूरे ब्लॉक हर जगह दोहराया है एक दृश्य को एक फॉर्म को संसाधित करने की आवश्यकता है। क्या ऐसा करने का कोई बेहतर तरीका नहीं है?

+0

Django कई वर्षों से जेनेरिक दृश्य है। यह प्रश्न और मेरे द्वारा देखे जाने वाले सभी उत्तर पुराने हैं। देखें: https://docs.djangoproject.com/en/1.9/ref/class-based-views/generic-editing/ – guettli

उत्तर

10

आप पुनरावृत्ति से बच सकते हैं। अधिकतर, आपको तर्क के रूप में फॉर्म और टेम्पलेट नाम के वर्ग के रूप में प्रवेश करने की आवश्यकता होती है, वैध फॉर्म जमा होने पर साफ डेटा को संसाधित करने के लिए एक कॉल करने योग्य, और इस तरह के प्रसंस्करण के बाद रीडायरेक्ट के लिए एक गंतव्य; इसके अलावा, आपको एक बार बाउंड या अनबाउंड फॉर्म बनाने के लिए फॉर्म क्लास को कॉल करने के लिए थोड़ा अतिरिक्त कोड चाहिए, और इसके साथ ठीक से निपटें। अर्थात्:

def process_any_form(request, 
        form_class, template_file_name, 
        process_data_callable, redirect_destination): 

    form = form_class(request.POST if request.method == 'POST' else None) 

    if form.is_bound and form.is_valid(): 
     process_data_callable(form.cleaned_data) 
     return HttpResponseRedirect(redirect_destination) 

    return render_to_response(template_file_name, {'form': form}) 
+2

यह काम करता है। यदि टेम्पलेट सिर्फ 'फ़ॉर्म' से अधिक चाहता है, तो आपको मानों के एक हैश को शामिल करने के लिए तर्क सूची को विस्तृत करने की आवश्यकता होगी। –

+0

एस/हैश/dict /, लेकिन, हाँ, अच्छा विचार: आप संदर्भ के लिए अर्ध-पूर्व-जनसंख्या वाले डी में प्रवेश कर सकते हैं, और प्रतिपादन के संदर्भ के रूप में dict (d, form = form) का उपयोग कर सकते हैं, इससे यह बनाता है समाधान और भी सामान्य। –

2

प्रसंस्करण प्रपत्रों का बॉयलरप्लेट तरीका दो चिंताओं को मिलाता है: परिणामों को संपादित और संसाधित करने के लिए एक फॉर्म प्रस्तुत करना। आप इसे दो तरीकों से तोड़ सकते हैं, जो समान render_to_response() कॉल के रूप में कुछ डुप्लिकेशंस पेश करेगा। जब तक आपने उस पर प्रतिक्रिया नहीं की, तो आप ऊपर से एकल विधि विधि से कम पढ़ने योग्य कुछ के साथ समाप्त हो सकते हैं।

जब मैं बॉयलरप्लेट विधि को देखता हूं, तो मुझे डुप्लिकेशन नहीं दिखाई देता है। ContactForm() के दो उपयोग अलग-अलग हैं। दो सशर्त मुझे लगता है कि एक फॉर्म को संसाधित करने में शामिल राज्य संक्रमणों को स्पष्ट रूप से स्पष्ट रूप से दिखाने के लिए प्रतीत होता है (एक खाली फॉर्म प्रस्तुत करें, जब तक कोई मान्य, प्रक्रिया-और-रीडायरेक्ट न हो) सबमिशन स्वीकार करें।

0

कोई ऐसा कार्य लिख सकता है जो सभी रूपों के लिए सशर्त को संभालता है। आप एक समारोह में जैसे, "is_valid" के बाद कि फार्म के लिए गुजर विशिष्ट कर ऐसा कर सकता है:

def FormHandler(request, CleaningFunction, redirecturl): 
    if request.method = 'POST': 
     if request.method == 'POST': # If the form has been submitted... 
      form = ContactForm(request.POST) # A form bound to the POST data 
      if form.is_valid(): # All validation rules pass 
       CleaningFunction(form) # Process the data in form.cleaned_data 
       return HttpResponseRedirect('/thanks/') # Redirect after POST 
    else: 
     form = ContactForm() # An unbound form 
    return form 

तो फिर आप अपने दृश्य से FormHandler कहेंगे। ध्यान दें कि यह परीक्षण नहीं किया गया है और इसमें त्रुटियां हो सकती हैं।

0

Django creating, editing, and deleting वस्तुओं के लिए कई सामान्य दृश्य प्रदान करता है। शायद आप इन कोशिश कर सकते हैं।

1

एलेक्स के सामान्य हैंडलर मुझे यह करने के लिए हरा, लेकिन FWIW हम उनके सुझाव के एक कम-जेनेरिक वर्जन की ओर जाते हैं:

def contact(request): 
    post_data = request.POST if request.method == 'POST' else None 
    form = ContactForm(post_data) 
    if request.method == 'POST': 
     # perform normal validation checking, etc 

    return render_to_response('contact.html', { 
     'form': form, 
     }) 

तो post_data कोई नहीं है, तो प्रपत्र होने के रूप में instantiated है असीम। अन्यथा, बाध्य प्रसंस्करण सामान्य के रूप में जारी है। यह ContactForm के एक डुप्लिकेट निर्माण से बचाता है, लेकिन मैं डेव के उत्तर से सहमत हूं कि डुप्लिकेट निर्माण मुझे डुप्लिकेट के रूप में परेशान नहीं करता है क्योंकि निर्माण पैरामीटर अलग हैं।

1

मैं इस से इतना थक गया कि मैंने इसे संभालने के लिए अपने स्वयं के सामान्य विचार लिखे हैं। इस प्रक्रिया में, मैंने पाया कि फॉर्म प्रसंस्करण के लिए django already has underdocumented generic views। वे दस्तावेजी जेनेरिक विचारों के काफी प्रत्यक्ष अनुरूप हैं, लेकिन फॉर्म स्वीकार करते हैं, और मूल रूप से उसी उदाहरण का पालन करते हैं जो आपने अपने उदाहरण में उपयोग किया था। आखिरकार, मैंने उन्हें अपने उपयोग के लिए बहुत लचीला और बेवकूफ पाया (मुझे एक create_or_update दृश्य नहीं चाहिए, मैं उन दो कार्यों को अलग से इलाज नहीं करना चाहता हूं।)

संपादित करें: आपको फ्रैग्सवर्थ के उत्तर पसंद नहीं आया, जो अंक उसी बात के बारे में मैं बात कर रहा हूं, मुझे लगता है कि आप मेरी तरह नहीं हैं। यह एक उदाहरण है कि यह कैसे काम करता है।

# in urls.py 
urlpatterns += patterns("", 
    (u'^...$', 'django.views.generic.create_update.update', { 
     'form_class': ContactForm }) 
) 

ContactForm एक save() विधि, और thats जहां आपके प्रपत्र संसाधन तर्क चला जाता है होना आवश्यक है।

0

आप django के रूपों मॉड्यूल को बाईपास कर सकते हैं और बस इसे पुराने फैशन तरीके से कर सकते हैं, आपको बहुत अधिक नुकसान के बिना अधिक लचीलापन मिलता है IMHO।

पिछली बार मैंने थोड़ी देर पहले django रूपों को देखा था, मुझे नहीं पता कि चीजें बदल गई हैं, लेकिन उदाहरण के लिए, यह वास्तव में आपको AJAX-शैली के रूप का निर्माण करने की अनुमति नहीं देता है; कम से कम आसानी से नहीं।

6

आप सही यह बेहतर हो सकता है कर रहे हैं, यहाँ एक बेहतर विकल्प (लेकिन पढ़ते रहते) है:

def contact(request): 
    form = ContactForm(request.POST or None) # A form bound to the POST data 
    if form.is_valid(): # All validation rules pass 
     # Process the data in form.cleaned_data 
     # ... 
     return HttpResponseRedirect('/thanks/') # Redirect after POST 

    return render_to_response('contact.html', { 
     'form': form, 
    }) 

यह टुकड़ा एक टॉक DjangoCon11 से Advanced Django Form Usage कहा जाता है से आता है।

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

def contact(request): 
    form = ContactForm(request.POST or None) # A form bound to the POST data 
    if request.method == 'POST' and form.is_valid(): # All validation rules pass 
     # Process the data in form.cleaned_data 
     # ... 
     return HttpResponseRedirect('/thanks/') # Redirect after POST 

    return render_to_response('contact.html', { 
     'form': form, 
    }) 
संबंधित मुद्दे