2009-05-15 15 views
8

मेरे पास एक स्थिति फ़ील्ड है जिसमें 3 मान हैं: लंबित, सक्रिय और अस्वीकार कर दिया गया। अगर मैं स्थिति के मूल्य को बदल रहा हूं, तो मैं पर एक जांच कर सकता हूं जिसे सक्रिय किया जा सकता है लंबित में बदला नहीं जा सकता है। मैं इसके लिए संग्रहीत-procs लिखना नहीं चाहता हूं। क्या मेरे पास बचत से पहले Django में पिछले मान हो सकता है?Django (django-admin) में मूल्य संक्रमण की जांच कैसे करें?

नए और पुराने मूल्य का मतलब है।

+0

+1 - मैं वही चीज़ सोच रहा हूं।मेरे मामले में कुछ भारी कर्तव्य कार्य है जो एक बचत विधि में किया जाता है जो केवल तभी आवश्यक होता है जब मॉडल के फ़ील्ड के किसी विशेष उप-समूह में कोई फ़ील्ड बदल गया हो, और मैं यह जांचने का एक तरीका ढूंढ रहा हूं कि यह मामला है या नहीं । धन्यवाद! –

उत्तर

10
def clean_status(self): 
    status = self.cleaned_data.get('status') 
    if status == 'pending': 
     if self.instance and self.instance.status == 'activated': 
      raise forms.ValidationError('You cannot change activated to pending') 

    return status 

यह विधि Form उपclass में जोड़ा जाना है। इसका नाम clean_FIELD_NAME है।

cleaned_data पिछले मान हैं। नया मान self.instance में संग्रहीत है।

वैकल्पिक रूप से, validate() विधि forms.Field उपclass में जोड़ा जा सकता है। See Django documentation.

+0

हे डोमिनिक रॉजर आप 'इनलाइन-डीजेंगो' में मदद कर सकते हैं। Django में मेरा प्रश्न – ha22109

8

आप इसे ओवरराइड save विधि में कर सकते हैं। याद रखने की बात यह है कि Django मॉडल उदाहरण वास्तविक डेटाबेस ऑब्जेक्ट्स नहीं हैं, वे लोड पर वहां से अपने मूल्य प्राप्त करते हैं। तो मौजूदा मान प्राप्त करने के लिए आप अपने वर्तमान ऑब्जेक्ट को सहेजने से पहले आसानी से डेटाबेस पर वापस जा सकते हैं।

def save(self, *args, **kwargs): 
    if self.status == 'pending': 
     old_instance = MyClass.objects.get(pk=self.pk) 
     if old_instance.status == 'activated': 
       raise SomeError 
    super(MyModel, self).save(*args, **kwargs) 

वर्तमान में अपवाद बढ़ाने के अलावा उपयोगकर्ता को एक त्रुटि संदेश लौटने का कोई अच्छा तरीका नहीं है। वर्तमान में 'मॉडल सत्यापन' को सक्षम करने के लिए Google ग्रीष्मकालीन कोड प्रोजेक्ट है, लेकिन यह कुछ महीनों तक तैयार नहीं होगा।

यदि आप व्यवस्थापक में कुछ ऐसा करना चाहते हैं, तो सबसे अच्छा तरीका एक कस्टम मॉडलफॉर्म को एक ओवरराइड clean() विधि के साथ परिभाषित करना है। हालांकि, इस बार यह एक रूप है क्योंकि आपके पास पहले से ही डीबी को मारने के बिना पुराने मूल्यों तक पहुंच है। एक अन्य लाभ यह है कि आप उपयोगकर्ता को एक फॉर्म सत्यापन त्रुटि वापस कर सकते हैं।

class MyModelForm(forms.ModelForm): 

    class Meta: 
      model = MyModel 

    def clean_status(self): 
     status = self.cleaned_data.get('status', '') 
     if status == 'pending': 
      if self.instance and self.instance.status == 'activated': 
        raise forms.ValidationError(
         'You cannot change activated to pending' 
       ) 
     return status 

class MyModelAdmin(forms.ModelAdmin): 
    form = MyModelForm 
    model = MyModel 
+0

ऐसा इसलिए है क्योंकि आपको शायद ModelAdmin.save_model विधि को ओवरराइड करना चाहिए: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-methods – ohnoes

+0

मैंने ऊपर दिए गए व्यवस्थापक का उपयोग करके एक विकल्प जोड़ा है। –

+0

अगर स्थिति होनी चाहिए, तो self.instance और self.instance.status == 'सक्रिय': फॉर्म बढ़ाएं। वैधता त्रुटि – ha22109

0

बचत विधि को ओवरराइड करने के बजाय, यह सिग्नल का उपयोग करने के लिए एक अच्छी जगह नहीं होगी? प्रतिबद्ध होने से पहले सहेजें को रोकें, डेटाबेस में वर्तमान मान की जांच करें, या तो सहेजें को आगे बढ़ाएं, या इसे अस्वीकार करें?

अब मुझे यकीन नहीं है कि सिग्नल सहेजने के अनुरोध को अवरुद्ध करता है या यदि यह एसिंच होता है, तो इस जवाब को कम करने के लिए स्वतंत्र महसूस करें यदि सत्यापन पर होने वाली बचत को रोकने के लिए सिग्नल का उपयोग नहीं किया जा सकता है।

यदि मैं एक और इनबिल्ट टूल भी करता हूं तो मैं इनबिल्ट विधियों को ओवरराइड करने के खिलाफ हूं।

+1

मुझे लगता है, ओवरराइटिंग सेव() और डिलीट() अच्छी प्रैक्टिस हो सकती है। मेरे पास कक्षाएं फोटो और थंबनेल हैं। थंब में एक आइटम = मॉडल है। ForeignKey (फोटो)। photo.delete() ओवरराइट किया गया है और सुपर (फोटो, स्वयं) .delete() चलाने से पहले सभी अंगूठे को हटा देगा (स्वयं। Thumbnail_set.all(): t.delete() में टी के लिए। अगर अंगूठे को हटाने से सिग्नल में किया जाएगा, तो कोड को बनाए रखना कठिन होगा। – vikingosegundo

+0

लेकिन __init__ I wolud कभी अधिभार नहीं। मैं इसके बजाय सिग्नल का उपयोग करूंगा। – vikingosegundo

1

यह स्टैक ओवरफ़्लो पर कहीं और उत्तर दिया गया है, लेकिन यह सही तरीका है कि फ़ील्ड गंदे हैं या नहीं, यह ट्रैक करने के लिए this जैसे कुछ का उपयोग करना है। फिर आप यह संकेत देने के लिए एक संकेत का उपयोग कर सकते हैं कि कुछ महत्वपूर्ण है जो महत्वपूर्ण है। (यानी आपका क्षेत्र)

0

एक ही प्रश्न के उत्तर की खोज करते समय यह धागा मिला। ऐसा कुछ क्यों नहीं करते? इस तरह आप डेटाबेस को छूने से बच सकते हैं। और इनबिल्ट __init__ बस थोड़ा बढ़ाया गया। मुझे लगता है कि सिग्नल का उपयोग करने से यह बहुत आसान तरीका है।

class MyModel(models.Model): 
    my_fair_field = .... 

    def __init__(self, *args, **kwargs): 
     super(MyModel, self).__init__(*args, **kwargs) 
     self.__clean_fair_field = self.my_fair_field 

    def save(self, *args, **kwargs): 
     # check if field value changed 
     if self.__clean_fair_field != self.my_fair_field 
       # ...do some work... 

     super(MyModel, self).save(*args, **kwargs) 
संबंधित मुद्दे