क्या Django के फॉर्म MVC का उल्लंघन कर रहे हैं?


16

मैंने बस स्प्रिंग एमवीसी के वर्षों से आने वाले Django के साथ काम करना शुरू कर दिया और रूपों के कार्यान्वयन को थोड़ा पागल होने के रूप में प्रहार किया। यदि आप परिचित नहीं हैं, तो Django फ़ॉर्म एक फॉर्म मॉडल वर्ग से शुरू होता है जो आपके क्षेत्रों को परिभाषित करता है। वसंत इसी तरह एक फार्म-बैकिंग ऑब्जेक्ट के साथ शुरू होता है। लेकिन जहां स्प्रिंग आपके JSP के भीतर बैकिंग ऑब्जेक्ट के लिए फॉर्म एलिमेंट्स को बाइंड करने के लिए एक टैगलिब प्रदान करता है, वहीं Django के पास सीधे मॉडल से बंधे हुए विजेट हैं। डिफ़ॉल्ट विगेट्स हैं जहां आप CSS लागू करने या नई कक्षाओं के रूप में पूरी तरह से कस्टम विजेट को परिभाषित करने के लिए अपने फ़ील्ड में शैली विशेषताएँ जोड़ सकते हैं। यह सब आपके अजगर कोड में जाता है। यह मुझे पागल लगता है। पहला, आप सीधे अपने मॉडल के बारे में अपने विचार की जानकारी रख रहे हैं और दूसरी यह कि आप अपने मॉडल को एक विशिष्ट दृश्य से जोड़ रहे हैं। क्या मैं कुछ भूल रहा हूँ?

संपादित करें: अनुरोध के अनुसार कुछ उदाहरण कोड।

Django:

# Class defines the data associated with this form
class CommentForm(forms.Form):
    # name is CharField and the argument tells Django to use a <input type="text">
    # and add the CSS class "special" as an attribute. The kind of thing that should
    # go in a template
    name = forms.CharField(
                widget=forms.TextInput(attrs={'class':'special'}))
    url = forms.URLField()
    # Again, comment is <input type="text" size="40" /> even though input box size
    # is a visual design constraint and not tied to the data model
    comment = forms.CharField(
               widget=forms.TextInput(attrs={'size':'40'}))

वसंत MVC:

public class User {
    // Form class in this case is a POJO, passed to the template in the controller
    private String firstName;
    private String lastName;
    get/setWhatever() {}
}

<!-- JSP code references an instance of type User with custom tags -->
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!-- "user" is the name assigned to a User instance -->
<form:form commandName="user">
      <table>
          <tr>
              <td>First Name:</td>
              <!-- "path" attribute sets the name field and binds to object on backend -->
              <td><form:input path="firstName" class="special" /></td>
          </tr>
          <tr>
              <td>Last Name:</td>
              <td><form:input path="lastName" size="40" /></td>
          </tr>
          <tr>
              <td colspan="2">
                  <input type="submit" value="Save Changes" />
              </td>
          </tr>
      </table>
  </form:form>

"सीधे आपके मॉडल में आपके विचार के बारे में जानकारी"? कृपया विशिष्ट रहें। "अपने मॉडल को एक विशिष्ट दृश्य से बांधना"? कृपया विशिष्ट रहें। कृपया ठोस, विशिष्ट उदाहरण प्रदान करें। इस तरह की एक सामान्य, हाथ से लहराती शिकायत को समझना मुश्किल है, बहुत कम प्रतिक्रिया।
S.Lott

मैंने अभी तक कुछ भी नहीं बनाया है, बस डॉक्स पढ़ना। आप सीएसएस कक्षाओं के साथ एक HTML विजेट को सीधे अपने फॉर्म वर्ग में पायथन कोड में बाँधते हैं। यही मैं बाहर बुला रहा हूं।
जिगी

आप इस बंधन में और क्या करना चाहते हैं? कृपया एक उदाहरण या एक लिंक या उस विशिष्ट चीज़ का उद्धरण प्रदान करें, जिस पर आपको आपत्ति हो। काल्पनिक तर्क का पालन करना कठिन है।
S.Lott

मैंने किया। देखो कि स्प्रिंग एमवीसी कैसे करता है। आप अपने दृश्य में फ़ॉर्म-बैकिंग ऑब्जेक्ट (जैसे Django फॉर्म क्लास) को इंजेक्ट करते हैं। फिर आप अपने HTML को टैगलिब का उपयोग करके लिखते हैं ताकि आप अपने HTML को सामान्य रूप से डिज़ाइन कर सकें और बस एक पथ विशेषता जोड़ सकें जो इसे आपके फॉर्म-बैकिंग ऑब्जेक्ट के गुणों से बाँध देगा।
जिग्गी

कृपया यह स्पष्ट करने के लिए कि आप क्या आपत्ति कर रहे हैं, सवाल को अपडेट करें । प्रश्न का पालन करना कठिन है। अपनी बात पूरी तरह स्पष्ट करने के लिए इसका कोई उदाहरण कोड नहीं है।
S.Lott

जवाबों:


21

हां, Django के रूप MVC के दृष्टिकोण से एक गड़बड़ है, मान लीजिए कि आप एक बड़े MMO सुपर-हीरो गेम में काम कर रहे हैं और आप हीरो मॉडल बना रहे हैं:

class Hero(models.Model):
    can_fly = models.BooleanField(default=False)
    has_laser = models.BooleanField(default=False)
    has_shark_repellent = models.BooleanField(default=False)

अब आपको इसके लिए एक फॉर्म बनाने के लिए कहा गया है, ताकि MMO खिलाड़ी अपने नायक को सुपर पॉवर प्रदान कर सकें:

class HeroForm(forms.ModelForm):
    class Meta:
        model = Hero

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

class HeroForm(forms.ModelForm):
    class Meta:
        model = Hero

    def clean(self):
        cleaned_data = super(HeroForm, self).clean()
        if cleaned_data['has_shark_repellent'] and cleaned_data['can_fly']:
            raise ValidationError("You cannot fly and repel sharks!")

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

  • एक और रूप लिखें जो हीरो मॉडल से संबंधित है।
  • एक स्क्रिप्ट लिखें जो नायकों को दूसरे गेम से आयात करती है।
  • खेल यांत्रिकी के दौरान मॉडल उदाहरण को मैन्युअल रूप से बदलें।
  • आदि।

यहाँ मेरा कहना यह है कि फ़ॉर्म-थ्रू फॉर्म फ़ॉर्म लेआउट और प्रस्तुति के बारे में है, आपको उस फ़ाइल में कभी भी व्यावसायिक तर्क नहीं जोड़ना चाहिए, जब तक कि आप स्पेगेटी कोड के साथ गड़बड़ न करें।

हीरो समस्या को संभालने का सबसे अच्छा तरीका मॉडल क्लीन विधि और एक कस्टम सिग्नल का उपयोग करना है। मॉडल क्लीन फॉर्म क्लीन की तरह काम करता है लेकिन इसका मॉडल में ही संग्रहित किया जाता है, जब भी HeroForm को साफ किया जाता है तो यह स्वचालित रूप से हीरो क्लीन विधि कहलाता है। यह एक अच्छा अभ्यास है क्योंकि अगर कोई अन्य डेवलपर हीरो के लिए कोई अन्य फॉर्म लिखता है तो उसे मुफ्त में विकर्षक / फ्लाई सत्यापन मिलेगा।

स्वच्छ के साथ समस्या यह है कि इसे केवल तभी कहा जाता है जब कोई मॉडल किसी प्रपत्र द्वारा संशोधित किया जाता है। इसे तब नहीं बुलाया जाता है जब आप इसे मैन्युअल रूप से सहेजते हैं () और आप अपने डेटाबेस में एक अमान्य नायक के साथ अंत कर सकते हैं। इस समस्या का सामना करने के लिए, आप इस श्रोता को अपनी परियोजना में जोड़ सकते हैं:

from django.db.models.signals import pre_save

def call_clean(sender, instance, **kwargs):
    instance.clean()
pre_save.connect(call_clean, dispatch_uid='whata')

यह आपके सभी मॉडलों के लिए प्रत्येक सेव () कॉल पर स्वच्छ पद्धति को कॉल करेगा।


यह एक बहुत ही उपयोगी उत्तर है। हालाँकि, मेरे कई रूपों और इसी मान्यता में कई मॉडल पर कई क्षेत्र शामिल हैं। मुझे लगता है कि यह विचार करने के लिए एक बहुत ही महत्वपूर्ण परिदृश्य है। मॉडल के स्वच्छ तरीकों में से एक पर आप इस तरह का सत्यापन कैसे करेंगे?
बोबोर्ट

8

आप पूरे स्टैक को मिला रहे हैं, इसमें कई परतें शामिल हैं:

  • एक Django मॉडल डेटा संरचना को परिभाषित करता है।

  • Django फ़ॉर्म HTML प्रपत्र, फ़ील्ड सत्यापन और पायथन / HTML मूल्य अनुवाद को परिभाषित करने के लिए एक शॉर्टकट है। इसकी सख्त जरूरत नहीं है, लेकिन अक्सर यह आसान है।

  • एक Django ModelForm एक और शॉर्टकट है, संक्षेप में एक फॉर्म सबक्लास जो एक मॉडल परिभाषा से अपने क्षेत्र प्राप्त करता है। सामान्य मामले के लिए बस एक आसान तरीका है जहां डेटाबेस में डेटा दर्ज करने के लिए एक फॉर्म का उपयोग किया जाता है।

और अंत में:

  • Django के आर्किटेक्ट MVC संरचना का बिल्कुल पालन नहीं करते हैं। कभी-कभी वे इसे एमटीवी (मॉडल टेम्पलेट व्यू) कहते हैं; क्योंकि नियंत्रक जैसी कोई चीज नहीं है, और टेम्पलेट (सिर्फ प्रस्तुति, कोई तर्क) और दृश्य (केवल उपयोगकर्ता-सामना करने वाले तर्क, कोई HTML) के बीच विभाजन मॉडल के अलगाव के रूप में महत्वपूर्ण नहीं है।

कुछ लोग इसे विधर्म के रूप में देखते हैं; लेकिन यह याद रखना महत्वपूर्ण है कि एमवीसी को मूल रूप से जीयूआई अनुप्रयोगों के लिए परिभाषित किया गया था, और यह वेब ऐप्स के लिए एक अजीब अजीब फिट है।


लेकिन विगेट्स प्रेजेंटेशन हैं और वे आपके फॉर्म में सीधे वायर्ड हो जाते हैं। निश्चित रूप से, मैं उनका उपयोग नहीं कर सकता, लेकिन तब आप बाध्यकारी और सत्यापन के लाभों को खो देते हैं। मेरा कहना है कि वसंत आपको मॉडल और दृश्य के बंधन और सत्यापन और पूर्ण पृथक्करण प्रदान करता है। मुझे लगता है कि Django आसानी से कुछ इसी तरह लागू किया जा सकता है। और मैं url कॉन्फ़िगरेशन को एक प्रकार के फ्रंट कंट्रोलर के रूप में देखता हूं जो स्प्रिंग एमवीसी के लिए काफी लोकप्रिय पैटर्न है।
jiggy

सबसे छोटा कोड जीतता है।
केविन क्लाइन

1
@ जिगी: प्रपत्र प्रस्तुति का हिस्सा हैं, बाध्यकारी और सत्यापन केवल उपयोगकर्ता द्वारा दर्ज किए गए डेटा के लिए है। मॉडल की अपनी बाध्यकारी और मान्यता है, रूपों से अलग और स्वतंत्र। जब वे 1: 1 (या लगभग)
जेवियर

बस थोड़ा सा ध्यान दें कि हां, MVC वास्तव में वेब ऐप्स में कोई मतलब नहीं था ... जब तक AJAX ने इसे फिर से वापस नहीं रखा।
अलेक्जेंडर

प्रपत्र प्रदर्शन दृश्य है। प्रपत्र सत्यापन नियंत्रक है। फॉर्म डेटा मॉडल है। IMO, कम से कम। Django उन सभी को एक साथ munges। एक तरफ पेडेंट्री, इसका मतलब है कि यदि आप समर्पित क्लाइंट-साइड डेवलपर्स को नियुक्त करते हैं (जैसा कि मेरी कंपनी करती है) तो यह पूरी तरह से बेकार है।
Jiggy

4

मैं इस पुराने प्रश्न का उत्तर दे रहा हूं क्योंकि अन्य उत्तर उल्लिखित विशिष्ट मुद्दे से बचने के लिए प्रतीत होते हैं।

Django रूपों आप आसानी से थोड़ा कोड लिखने के लिए और समझदार चूक के साथ एक फार्म बनाने के लिए अनुमति देते हैं। अनुकूलन की कोई भी राशि बहुत जल्दी "अधिक कोड" और "अधिक काम" की ओर ले जाती है और कुछ हद तक फॉर्म सिस्टम के प्राथमिक लाभ को कम कर देती है

साँचा पुस्तकालयों जैसे django- विजेट-ट्वीक्स के रूप अनुकूलित करना बहुत आसान बनाते हैं। उम्मीद है कि इस तरह क्षेत्र अनुकूलन अंततः वेनिला Django स्थापना के साथ आसान हो जाएगा।

आपका उदाहरण django-widget-tweaks के साथ:

{% load widget_tweaks %}
<form>
  <table>
      <tr>
          <td>Name:</td>
          <td>{% render_field form.name class="special" %}</td>
      </tr>
      <tr>
          <td>Comment:</td>
          <td>{% render_field form.comment size="40" %}</td>
      </tr>
      <tr>
          <td colspan="2">
              <input type="submit" value="Save Changes" />
          </td>
      </tr>
  </table>


1

(मैंने इसे अधिक सुपाठ्य बनाने के लिए MVC अवधारणाओं को सूचित करने के लिए इटैलिक का उपयोग किया है ।)

नहीं, मेरी राय में, वे एमवीसी को नहीं तोड़ते हैं। Django मॉडल / फॉर्म के साथ काम करते समय, एक मॉडल के रूप में संपूर्ण MVC स्टैक का उपयोग करने के बारे में सोचें :

  1. django.db.models.Modelआधार मॉडल है (डेटा और व्यावसायिक तर्क रखता है)।
  2. django.forms.ModelFormके साथ बातचीत के लिए एक नियंत्रक प्रदान करता है django.db.models.Model
  3. django.forms.Form(जैसा कि विरासत के माध्यम से प्रदान किया गया है django.forms.ModelForm) वह दृश्य है जिसके साथ आप सहभागिता करते हैं।
    • इससे चीजें धुंधली हो जाती हैं, क्योंकि ModelFormयह एक है Form, इसलिए दो परतों को कसकर युग्मित किया जाता है। मेरी राय में, यह हमारे कोड में संक्षिप्तता के लिए, और Django डेवलपर्स के कोड के भीतर कोड फिर से उपयोग के लिए किया गया था।

इस तरह, django.forms.ModelForm(अपने डेटा और व्यापार तर्क के साथ) एक मॉडल ही बन जाता है। आप इसे (एमवीसी) वीसी के रूप में संदर्भित कर सकते हैं, जो ओओपी में एक बहुत ही सामान्य कार्यान्वयन है।

उदाहरण के लिए, Django की django.db.models.Modelक्लास लें। जब हम django.db.models.Modelवस्तुओं को देखते हैं, तो हम मॉडल को देखते हैं, हालांकि यह पहले से ही एमवीसी का पूर्ण कार्यान्वयन है। MySQL मान लें कि बैक एंड डेटाबेस है:

  • MySQLdbहै मॉडल (डाटा संग्रहण परत है, और व्यापार के बारे में तर्क कैसे सहभागिता के साथ / सत्यापित करें डेटा)।
  • django.db.models.queryहै नियंत्रक (से हैंडल इनपुट दृश्य और के लिए इसकी अनुवाद मॉडल )।
  • django.db.models.Modelहै दृश्य (क्या के साथ उपयोगकर्ता इंटरैक्ट करने)।
    • इस मामले में, डेवलपर्स (आप और मैं) 'उपयोगकर्ता' हैं।

यह इंटरएक्शन आपके "क्लाइंट-साइड डेवलपर्स" के समान है, जब ऑब्जेक्ट्स के साथ काम कर रहा है yourproject.forms.YourForm(इनहेरिट कर रहा है django.forms.ModelForm):

  • जैसा कि हमें यह जानने की जरूरत है कि कैसे बातचीत django.db.models.Modelकरनी है, उन्हें यह जानना होगा कि yourproject.forms.YourFormउनके ( मॉडल ) के साथ कैसे बातचीत करनी है ।
  • जैसा कि हमें इसके बारे में जानने की आवश्यकता नहीं है MySQLdb, आपके "क्लाइंट-साइड डेवलपर्स" को इसके बारे में कुछ भी जानने की आवश्यकता नहीं है yourproject.models.YourModel
  • दोनों ही मामलों में, हमें शायद ही कभी इस बारे में चिंता करने की आवश्यकता है कि नियंत्रक वास्तव में कैसे लागू किया जाता है।

1
बहस शब्दार्थ के बजाय, मैं बस अपने HTML और CSS को अपने टेम्पलेट में रखना चाहता हूं और इसे किसी भी .py फाइल में नहीं रखना है। एक तरफ दर्शन, यह सिर्फ एक व्यावहारिक अंत है जिसे मैं प्राप्त करना चाहता हूं क्योंकि यह अधिक कुशल है और श्रम के बेहतर विभाजन की अनुमति देता है।
जिग्गी जूल

1
यह अभी भी पूरी तरह से संभव है। आप मैन्युअल रूप से अपने फ़ील्ड को टेम्प्लेट्स में लिख सकते हैं, मैन्युअल रूप से अपने विचारों में अपना सत्यापन लिख सकते हैं, और फिर मैन्युअल रूप से अपने मॉडल को अपडेट कर सकते हैं। लेकिन Django के फ़ॉर्म का डिज़ाइन MVC को नहीं तोड़ता है।
जैक एम।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.