2011-09-09 16 views
28

जोड़ना मेरे पास एक प्रारंभिक और समाप्ति तिथि सीमा वाला एक Django मॉडल है। मैं सत्यापन को लागू करना चाहता हूं ताकि कोई भी दो रिकॉर्ड दिनांक सीमाओं को ओवरलैप न कर सके। इसे लागू करने का सबसे आसान तरीका क्या है कि मुझे इस तर्क को लिखने के लिए खुद को दोहराना नहीं है?कस्टम Django मॉडल प्रमाणीकरण

उदा। मैं एक फार्म में इस तर्क को फिर से लागू नहीं करना चाहती और एक ModelFormऔर एक व्यवस्थापक प्रपत्र और मॉडल अधिरोहित save()

जहां तक ​​मुझे पता है, Django इन प्रकार के मानदंडों को विश्व स्तर पर लागू करना आसान नहीं बनाता है।

गुगलिंग बहुत उपयोगी नहीं रहा है, क्योंकि "मॉडल सत्यापन" आमतौर पर विशिष्ट मॉडल फ़ील्ड को मान्य करने के लिए संदर्भित करता है, न कि संपूर्ण मॉडल सामग्री, या फ़ील्ड के बीच संबंध।

उत्तर

27

बुनियादी पैटर्न जो मुझे उपयोगी, save() अंदर से clean() में मेरे सभी कस्टम सत्यापन डाल करने के लिए और फिर बस full_clean() फोन (जो clean() और कुछ अन्य तरीकों कॉल) है जैसे:

class BaseModel(models.Model): 

    def clean(self, *args, **kwargs): 
     # add custom validation here 
     super(BaseModel, self).clean(*args, **kwargs) 

    def save(self, *args, **kwargs): 
     self.full_clean() 
     super(BaseModel, self).save(*args, **kwargs) 

यह डिफ़ॉल्ट रूप से नहीं किया गया है, जैसा कि here समझाया गया है, क्योंकि यह कुछ विशेषताओं में हस्तक्षेप करता है, लेकिन यह मेरे आवेदन के लिए कोई समस्या नहीं है।

8

मुझे लगता है कि आप इस का उपयोग करना चाहिए: https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects

बस इस तरह अपने मॉडल में साफ() विधि को परिभाषित: (डॉक्स लिंक से उदाहरण)

def clean(self): 
    from django.core.exceptions import ValidationError 
    # Don't allow draft entries to have a pub_date. 
    if self.status == 'draft' and self.pub_date is not None: 
     raise ValidationError('Draft entries may not have a publication date.') 
    # Set the pub_date for published items if it hasn't been set already. 
    if self.status == 'published' and self.pub_date is None: 
     self.pub_date = datetime.datetime.now() 
+0

यह करीब है। मुझे अपने मॉडल की सेव() को ओवरराइड करना पड़ा, और वहां से क्लीन() को कॉल करना पड़ा। – Cerin

+1

लेकिन क्या के लिए? AdminSite (ModelForm) स्वचालित रूप से साफ़() को कॉल करता है। लेकिन सेव() विधि से साफ() को कॉल करना अप्रत्याशित पल में प्रमाणीकरण त्रुटि उत्पन्न कर सकता है और इसे अपेक्षित के रूप में नहीं माना जाएगा। – alTus

+6

सबकुछ साफ नहीं है। यह सत्यापित किए जाने की आवश्यकता है कि यह कहां से बचाया गया है। भ्रष्ट डेटा के लिए टूटा हुआ साइट पेज बेहतर है। – Cerin

16

मैं पर validate_unique विधि को ओवरराइड करेगी आदर्श। सुनिश्चित करें कि आप वर्तमान वस्तु जब मान्य उपेक्षा करने के लिए, आप निम्नलिखित का उपयोग कर सकते हैं:

from django.db.models import Model, DateTimeField 
from django.core.validators import NON_FIELD_ERRORS, ValidationError 

class MyModel(Model): 
    start_date = DateTimeField() 
    end_date = DateTimeField() 

    def validate_unique(self, *args, **kwargs): 
     super(MyModel, self).validate_unique(*args, **kwargs) 

     qs = self.__class__._default_manager.filter(
      start_date__lt=self.end_date, 
      end_date__gt=self.start_date 
     ) 

     if not self._state.adding and self.pk is not None: 
      qs = qs.exclude(pk=self.pk) 

     if qs.exists(): 
      raise ValidationError({ 
       NON_FIELD_ERRORS: ['overlapping date range',], 
      }) 

ModelForm स्वचालित रूप से एक full_clean(), जो आप मैन्युअल रूप से भी उपयोग कर सकते हैं के माध्यम से आप के लिए यह कॉल करेंगे।

पीपीआर की एक साधारण, सही range overlap condition की अच्छी चर्चा है।

+0

django 1.3.1 पर मैं प्रमाणीकरण को बढ़ाने में एक समस्या में भाग रहा हूं जिस तरह से आप इसका वर्णन करते हैं।अपवाद उठाते समय मैं एक स्ट्रिंग error_msg के बजाय {field: (error_msg,)} dict को पार करके इसे ठीक करने में सक्षम था। – adam

+5

'django.core.exceptions से ValidationError आयात करते हैं, NON_FIELD_ERRORS' ' बढ़ा ValidationError ({NON_FIELD_ERRORS: ('अतिव्यापी तिथि सीमा',)}) ' – adam

+2

वहाँ विस्तार' validate_unique' के बजाय सिर्फ 'clean' को परिभाषित करने में कोई दिलचस्पी नहीं है ? कोड व्यवस्थित करने का सिर्फ एक प्रश्न? – lajarre

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