django - request.POST ऑब्जेक्ट अपरिवर्तनीय क्यों है?


109

जैसा कि शीर्षक पूछता है, Django के लोगों ने अनुरोध को लागू करने का फैसला क्यों किया था ।POST ऑब्जेक्ट को एक क्वेरी के साथ (जो निश्चित रूप से, पूरे मामले को अपरिवर्तनीय बनाता है?)

मुझे पता है कि आप पोस्ट डेटा की एक प्रति बनाकर इसे संशोधित कर सकते हैं

post = request.POST.copy()

लेकिन ऐसा क्यों? निश्चित रूप से यह सरल होगा कि किसी भी तरह बात को बदलने की अनुमति दी जाए? या यह किसी और कारण से भी इस्तेमाल किया जा रहा है जो समस्या का कारण हो सकता है?


1
आप इसे क्यों बदलना चाहते हैं? आप इससे डेटा ले सकते हैं और इसे अपने विचार में उपयोग / संशोधित कर सकते हैं। इसमें डेटा जोड़कर, आप यह धारणा बना सकते हैं कि request.POSTवास्तव में जितना डेटा है उससे अधिक डेटा के साथ प्रस्तुत किया गया है।
शिमोन विसेर

11
ऐसा नहीं है कि मैं चाहता हूं कि यह परस्पर हो। इससे अधिक नहीं, कहते हैं, मैं चाहता हूं कि आइसक्रीम ठंडा हो। आइसक्रीम के मामले में, अगर यह ठंडा नहीं है , तो यह पिघल जाता है और फिर आप एक बड़ा राजभाषा 'गड़बड़ करने के लिए डांटते हैं। लेकिन request.POST ऑब्जेक्ट के साथ ... मेरा मतलब है, अगर मैं अपना कोड खराब करने जा रहा हूं, तो मैं इसे खराब कर दूंगा। मुझे नहीं पता था कि POST ऑब्जेक्ट्स और कॉज़िंग प्रॉब्लम्स में डेटा जोड़ने वाले डेवलपर्स की एक स्थानिकमारी थी, इसलिए यह "फिक्स" को लक्षित करने के लिए एक अजीब बात की तरह लगता है।
भावल

अच्छा प्रश्न; यह वास्तव में कभी नहीं सोचा था।
बुरहान खालिद

1
यह मेरे लिए छिटपुट रूप से सामने आया क्योंकि मेरे क्लाइंट ने कभी-कभी JSON डेटा (म्यूटेबल) और कभी-कभी URL फॉर्म एन्कोडेड (अपरिवर्तनीय) संदेश सबमिट किए थे।
ओवेनफी

2
गैर-अंग्रेजी बोलने वालों के लिए, "उत्परिवर्तन" एक शब्द नहीं है - सही वाक्यांश है "आप इसे म्यूट कर सकते हैं" या "आप इसे संशोधित कर सकते हैं"। डेवलपर्स को लिंग करने की भी कोई आवश्यकता नहीं है - आप "Django टीम" या "कोर देव" का उपयोग "दोस्तों" के बजाय कर सकते हैं।
एलेक्समुलर

जवाबों:


131

यह एक रहस्य का एक सा है, है ना? कई सतही प्रशंसनीय सिद्धांत जांच पर गलत साबित होते हैं:

  1. ताकि POSTवस्तु उत्परिवर्तन विधियों को लागू करने के लिए नहीं है? नहीं: POSTवस्तु के अंतर्गत आता है django.http.QueryDictवर्ग जो औजार सहित उत्परिवर्तन तरीकों का एक पूरा सेट, __setitem__, __delitem__, popऔर clear। जब आप उत्परिवर्तन विधियों में से किसी एक को कॉल करते हैं तो यह ध्वज की जांच करके अपरिवर्तनीयता को लागू करता है। और जब आप copyविधि को कॉल करते हैं तो आपको QueryDictम्यूट किए गए ध्वज के साथ एक और उदाहरण मिलता है ।

  2. प्रदर्शन में सुधार के लिए? नहीं: QueryDictपरिवर्तनशील ध्वज को बंद करने पर वर्ग को कोई प्रदर्शन लाभ नहीं मिलता है।

  3. ताकि POSTवस्तु को शब्दकोश कुंजी के रूप में इस्तेमाल किया जा सके? नहीं: QueryDictवस्तुएं धोने योग्य नहीं हैं।

  4. जैसा कि यहां दावा किया गया है कि POSTडेटा को आलसी (पूरी प्रतिक्रिया पढ़ने के लिए प्रतिबद्ध किए बिना) बनाया जा सकता है ? मैं कोड में इस बात का कोई सबूत नहीं है देखें: जहाँ तक मैं बता सकता हूँ, प्रतिक्रिया के पूरे हमेशा की तरह, पढ़ने के लिए है या तो सीधे या के माध्यम से MultiPartParserके लिए multipartप्रतिक्रियाओं।

  5. प्रोग्रामिंग त्रुटियों के खिलाफ आपकी सुरक्षा के लिए? मैंने यह दावा करते हुए देखा है, लेकिन मैंने कभी इस बात की अच्छी व्याख्या नहीं देखी कि ये त्रुटियां क्या हैं, और कैसे अपरिवर्तनशीलता आपको उनके खिलाफ बचाती है।

किसी भी मामले में, POSTहै हमेशा अडिग नहीं : जब प्रतिक्रिया है multipart, तो POSTपरिवर्तनशील है। ऐसा लगता है कि kibosh उन अधिकांश सिद्धांतों पर रखा गया है जिनके बारे में आप सोच सकते हैं। (जब तक कि यह व्यवहार एक नज़र न हो।)

सारांश में, मैं Django में POSTवस्तु के गैर- multipartअनुरोधों के लिए अपरिवर्तनीय होने के लिए कोई स्पष्ट तर्क नहीं देख सकता ।


मैं इस तरह Django में किसी न किसी किनारों के टन देखा है। हालांकि किसी बिंदु पर किसी को समझ में आया होगा।
दान पसारो

2
मैंने इसे एक और स्टैक उत्तर में पाया: "और इसे अपरिवर्तनीय होना चाहिए ताकि इसे आलसी बनाया जा सके। कॉपी सभी POST डेटा प्राप्त कर रहा है। कॉपी होने तक, यह सब प्राप्त नहीं हो सकता है। आगे, एक बहु-थ्रेडिंग WSGI के लिए। सर्वर काफी अच्छी तरह से काम करने के लिए, यह मददगार है अगर यह अपरिवर्तनीय है "
Seaux

12
जब आप उन पर टिप्पणी करने का इरादा करते हैं तो @Seaux आपको lazily SO SO उत्तर नहीं पढ़ना चाहिए। ;-)
क्रिस वेसलिंग

3
@ क्रिसहेलिंग मैं देख रहा हूं कि आपने वहां क्या किया था
Seaux

2
इससे भी बेहतर, जब मैं django test क्लाइंट पर मुकदमा भेजने का अनुरोध करता हूं, तो क्वेरी को म्यूट किया जाता है।
user1158559

82

यदि अनुरोध एक Django formजमा करने का परिणाम था , तो यह POST के लिए उचित immutableहै कि वह फॉर्म सबमिशन और फॉर्म सत्यापन के बीच डेटा की अखंडता को सुनिश्चित करे । हालाँकि, यदि अनुरोध Django जमा करने के माध्यम से नहीं भेजा गया था , तो POST है क्योंकि कोई प्रपत्र सत्यापन नहीं है।formmutable

आप हमेशा कुछ ऐसा कर सकते हैं: ( @ leo-the-manic's comment के अनुसार )

#  .....
mutable = request.POST._mutable
request.POST._mutable = True
request.POST['some_data'] = 'test data'
request.POST._mutable = mutable
# ......

3
@ जोश: मुझे लगता है कि टिप्पणीकार POST को परिवर्तनशील बनाना चाहता था, और इस उत्तर में कोड स्निपेट ने मदद की।
श्रीवत्सआर

आप नई कुंजी, मूल्य जोड़ सकते हैं लेकिन आप मौजूदा डेटा को बदल नहीं सकते।
वामसीधर मुगुल्ला

अच्छा लगा। और मुझे यकीन है कि जो भी इस कोड का उपयोग करेगा वह जानता है कि वह क्या कर रहा है।
जॉन पैंग

@VamsidharMuggulla जोड़ना और बदलना दोनों संभव है। यहां तक ​​कि हटाने की भी अनुमति है।
एंटनी हैचकिंस

5

अपडेट :

गैरेथ रीस सही थे कि इस मामले में बिंदु 1 और 3 मान्य नहीं थे। हालांकि मुझे लगता है कि बिंदु 2 और 4 अभी भी मान्य हैं, इसलिए मैं यहां शोध छोड़ दूंगा।

(मैंने देखा कि request.POSTपिरामिड (तोरण) और Django दोनों का उद्देश्य कुछ रूप है MultiDict। इसलिए शायद यह request.POSTअपरिवर्तनीय बनाने की तुलना में अधिक सामान्य अभ्यास है । "


मैं Django के लोगों के लिए नहीं बोल सकता, हालांकि मुझे लगता है कि यह इन कारणों में से कुछ के कारण हो सकता है:

  1. प्रदर्शन । अपरिवर्तनीय वस्तुएं उन लोगों के बीच "अधिक तेज़" होती हैं, जिनमें वे पर्याप्त अनुकूलन की अनुमति देते हैं। एक ऑब्जेक्ट अपरिवर्तनीय है इसका मतलब है कि हम निर्माण समय पर इसके लिए जगह आवंटित कर सकते हैं , और अंतरिक्ष आवश्यकताओं को नहीं बदल रहे हैं। इसमें कॉपी दक्षता और तुलनात्मक दक्षता जैसी चीजें भी हैं। संपादित करें : यहQueryDictगैरेथ रीस ने बताया कि ऐसा नहीं है।
  2. के मामले में request.POST, ऐसा लगता है कि सर्वर साइड में किसी भी गतिविधि को अनुरोध के डेटा को बदलने की आवश्यकता नहीं है । और इसलिए अपरिवर्तनीय वस्तुएं अधिक अनुकूल हैं, यह उल्लेख करने के लिए नहीं कि उनके पास पर्याप्त प्रदर्शन लाभ है।
  3. अपरिवर्तनीय वस्तुओं को dictकुंजियों के रूप में इस्तेमाल किया जा सकता है , जो मुझे लगता है कि Django में कहीं बहुत उपयोगी हो सकता है .. संपादित करें : मेरी गलती, अपरिवर्तनीय सीधे धोने योग्य नहीं है ; हालांकि, धुलाई योग्य वस्तुएं आमतौर पर अपरिवर्तनीय होती हैं ।
  4. जब आप request.POST(विशेषकर थर्ड-पार्टी प्लग इन और आउट) पास होते हैं, तो आप उम्मीद कर सकते हैं कि उपयोगकर्ता की यह अनुरोध वस्तु अपरिवर्तित रहेगी।

किसी तरह से ये कारण "अपरिवर्तनीय बनाम उत्परिवर्तनीय" के सामान्य उत्तर भी हैं। सवाल। मुझे यकीन है कि Django मामले में ऊपर की तुलना में बहुत अधिक डिजाइन विचार हैं।


1
अंतिम मामला वास्तव में महत्वपूर्ण है। यह वास्तव में सुरक्षा के बारे में है। यही कारण है कि Django प्रदान करता है sessionsजो राज्यों के बीच डेटा प्राप्त करने और संशोधित करने का अल्पकालिक तरीका है।
CppLearner

2
आपकी बात (1) इस मामले में जवाब नहीं हो सकती है, क्योंकि POSTएक QueryDictवस्तु है , और इन वस्तुओं को अपरिवर्तनीय होने से कोई प्रदर्शन लाभ नहीं मिलता है। और आपकी बात (3) का जवाब नहीं हो सकता है, क्योंकि QueryDictऑब्जेक्ट्स हैशेबल नहीं हैं, और इसलिए इसका इस्तेमाल शब्दकोश कीज़ के रूप में नहीं किया जा सकता है।
गारेथ रीस

@GarethRees ये इंगित करने के लिए धन्यवाद। वास्तव में मैं गलत था। मैंने इन्हें सही करने के लिए अपना उत्तर अपडेट किया। मुझे QueryDictजवाब देने से पहले अधिक ध्यान देना चाहिए था ।
KZ

7
@CppLearner सुरक्षा बिंदु मूक लगता है, जैसेrequests.POST._mutable = True; requests.POST['foo'] = 'bar'; request.POST._mutable = False
डेन पासारो

4

मुझे यह पसंद है कि यह डिफ़ॉल्ट रूप से अपरिवर्तनीय है। जैसा कि आपको बताया गया है कि यदि आप की जरूरत है, तो आप इसे परिवर्तनशील बना सकते हैं, लेकिन आपको इसके बारे में स्पष्ट होना चाहिए। यह 'मुझे पता है कि मैं एक बुरे सपने को खत्म कर सकता हूं, लेकिन मुझे पता है कि मैं अब क्या कर रहा हूं।'


2

मुझे यह स्टैक उत्तर https://stackoverflow.com/a/2339963 पर एक टिप्पणी में मिला

और इसे अपरिवर्तनीय होना चाहिए ताकि इसे आलसी बनाया जा सके। प्रतिलिपि सभी POST डेटा प्राप्त कर रही है। प्रतिलिपि होने तक, यह सब प्राप्त नहीं हो सकता है। इसके अलावा, बहु-थ्रेडेड WSGI सर्वर के लिए यथोचित रूप से अच्छी तरह से काम करने के लिए, यह सहायक है यदि यह अपरिवर्तनीय है


1

कृपया ध्यान दें: multipartDjango 1.11 https://github.com/django/django/blob/stable/1.11.x/django/http/multipartparser.py#L292 से अनुरोध अपरिवर्तनीय है

वे पिछले संस्करणों में परिवर्तनशील थे।


Django के 1.11 रिलीज नोट्स में भी उल्लेख किया गया है ।
djvg
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.