एक Django मॉडल में एक संख्यात्मक क्षेत्र के अधिकतम मूल्य को कैसे सीमित करें?


169

Django के मॉडल में उपयोग के लिए विभिन्न संख्यात्मक क्षेत्र उपलब्ध हैं, जैसे DecimalField और PositiveIntegerField । यद्यपि पूर्व को संग्रहीत दशमलव स्थानों की संख्या और संग्रहीत किए गए वर्णों की कुल संख्या तक सीमित किया जा सकता है, लेकिन क्या इसे केवल एक निश्चित सीमा के भीतर केवल संख्याओं को संग्रहीत करने के लिए प्रतिबंधित करने का कोई तरीका है , जैसे कि 0.0-5.0?

असफल होना, क्या किसी पॉजिटिवइंटरफ़िल्ड को केवल स्टोर करने के लिए प्रतिबंधित करना है, उदाहरण के लिए, 50 तक की संख्या?

अद्यतन: अब बग 6845 बंद कर दिया गया है , यह StackOverflow प्रश्न मूट हो सकता है। - संपोलोक्कुपर


आप प्री-सेव सिग्नल बना सकते हैं: http://docs.djangoproject.com/en/dev/ref/signals/#django.db.models.signals.pre_save
igorgue

मुझे यह उल्लेख करना चाहिए कि मैं यह भी चाहता हूं कि जोंगो के प्रशासन में प्रतिबंध लागू हो। यह प्राप्त करने के लिए, कम से कम, प्रलेखन में यह कहना है: docs.djangoproject.com/en/dev/ref/contrib/admin/…
sampablokuper

वास्तव में, प्री -१.० जिआंगो को लगता है कि वास्तव में एक सुंदर समाधान था: cotellese.net/2007/12/11/… । मुझे आश्चर्य है कि अगर Django के svn रिलीज में ऐसा करने का एक समान रूप से सुरुचिपूर्ण तरीका है।
सम्पाब्लोकपर

मुझे यह जानकर निराशा हुई कि वर्तमान Django svn के साथ ऐसा करने का एक सुंदर तरीका प्रतीत नहीं होता है। अधिक जानकारी के लिए इस चर्चा धागा देखें: groups.google.com/group/django-users/browse_thread/thread/...
sampablokuper

मॉडल पर सत्यापनकर्ताओं का उपयोग करें, और सत्यापन व्यवस्थापक इंटरफ़ेस और मॉडलफ़ॉर्म
guettli

जवाबों:


133

आप एक कस्टम मॉडल फ़ील्ड प्रकार भी बना सकते हैं - http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields देखें

इस मामले में, आप अंतर्निहित इंटेगरफिल्ड से 'इनहेरिट' कर सकते हैं और इसके सत्यापन तर्क को ओवरराइड कर सकते हैं।

जितना मैं इस बारे में सोचता हूं, मुझे एहसास होता है कि यह कई Django ऐप्स के लिए कितना उपयोगी होगा। शायद ट्रंक को जोड़ने पर विचार करने के लिए Django के देवों के लिए एक IntegerRangeField प्रकार को पैच के रूप में प्रस्तुत किया जा सकता है।

यह मेरे लिए काम कर रहा है:

from django.db import models

class IntegerRangeField(models.IntegerField):
    def __init__(self, verbose_name=None, name=None, min_value=None, max_value=None, **kwargs):
        self.min_value, self.max_value = min_value, max_value
        models.IntegerField.__init__(self, verbose_name, name, **kwargs)
    def formfield(self, **kwargs):
        defaults = {'min_value': self.min_value, 'max_value':self.max_value}
        defaults.update(kwargs)
        return super(IntegerRangeField, self).formfield(**defaults)

फिर अपने मॉडल वर्ग में, आप इसका उपयोग इस तरह से करेंगे (क्षेत्र जहाँ आप उपरोक्त कोड डालते हैं, वह मॉड्यूल है):

size = fields.IntegerRangeField(min_value=1, max_value=50)

या नकारात्मक और सकारात्मक की एक सीमा के लिए (जैसे एक थरथरानवाला रेंज):

size = fields.IntegerRangeField(min_value=-100, max_value=100)

क्या वास्तव में अच्छा होगा अगर इसे इस तरह के रेंज ऑपरेटर के साथ बुलाया जा सकता है:

size = fields.IntegerRangeField(range(1, 50))

लेकिन, इसके लिए बहुत अधिक कोड की आवश्यकता होगी क्योंकि आप एक 'स्किप' पैरामीटर - रेंज (1, 50, 2) निर्दिष्ट कर सकते हैं - ज्ञान विचार ... ...


यह काम करता है लेकिन जब मॉडल की स्वच्छ विधि में, पूर्णांक का मान हमेशा कोई नहीं होता है जो इसे बनाता है तो मैं इसे कोई अतिरिक्त सफाई प्रदान नहीं कर सकता। किसी भी विचार यह क्यों है और इसे कैसे ठीक किया जाए?
KrisF

2
आप MinValueValidator(min_value) and MaxValueValidator(max_value)कॉल करने से पहले जोड़कर अपने कस्टम फ़ील्ड को बढ़ा सकते हैं super().__init__ ...(स्निपेट: gist.github.com/madneon/147159f46ed478c71d5ee4950a9d697d )
madneon

348

आप Django के अंतर्निहित सत्यापनकर्ताओं का उपयोग कर सकते हैं -

from django.db.models import IntegerField, Model
from django.core.validators import MaxValueValidator, MinValueValidator

class CoolModelBro(Model):
    limited_integer_field = IntegerField(
        default=1,
        validators=[
            MaxValueValidator(100),
            MinValueValidator(1)
        ]
     )

संपादित करें : मॉडल के साथ सीधे काम करते समय, सत्यापनकर्ताओं को ट्रिगर करने के लिए मॉडल को सहेजने से पहले मॉडल को full_clean विधि से कॉल करना सुनिश्चित करें । ModelFormरूपों का उपयोग करते समय स्वचालित रूप से ऐसा करने की आवश्यकता नहीं होती है ।


4
मुझे लगता है कि यदि आप चाहते हैं कि आप limited_integer_field को वैकल्पिक रूप में अच्छी तरह से लिखना चाहते हैं, तो आपको अपना सत्यापनकर्ता लिखना होगा? (केवल मान्य सीमा यदि रिक्त नहीं है) शून्य = सत्य, रिक्त = सत्य नहीं है ..
radtek

2
Django में 1.7 सेटिंग null=Trueऔर blank=Trueउम्मीद के मुताबिक काम करता है। फ़ील्ड वैकल्पिक है और यदि यह रिक्त है तो इसे शून्य के रूप में संग्रहीत किया जाता है।
टिम टिस्डाल

77
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator

size = models.IntegerField(validators=[MinValueValidator(0),
                                       MaxValueValidator(5)])

52

मुझे भी यही समस्या थी; यहाँ मेरा समाधान था:

SCORE_CHOICES = zip( range(1,n), range(1,n) )
score = models.IntegerField(choices=SCORE_CHOICES, blank=True)

10
एक सूची समझ का उपयोग करना:models.IntegerField(choices=[(i, i) for i in range(1, n)], blank=True)
राजाजी अबूइसा

10

इसे करने के दो तरीके हैं। 50 से अधिक की संख्या को किसी उपयोगकर्ता द्वारा दर्ज नहीं करने के लिए फॉर्म सत्यापन का उपयोग करना है। फॉर्म सत्यापन डॉक्स

यदि प्रक्रिया में कोई उपयोगकर्ता शामिल नहीं है, या आप डेटा दर्ज करने के लिए फ़ॉर्म का उपयोग नहीं कर रहे हैं, तो आपको saveअपवाद को फेंकने या फ़ील्ड में जाने वाले डेटा को सीमित करने के लिए मॉडल की विधि को ओवरराइड करना होगा ।


2
आप गैर-मानव इनपुट को मान्य करने के लिए भी एक फॉर्म का उपयोग कर सकते हैं। यह ऑल-अराउंड सत्यापन तकनीक के रूप में फॉर्म को पॉप्युलेट करने के लिए बहुत अच्छा काम करता है।
S.Lott

1
इस पर सोचने के बाद, मुझे पूरा यकीन है कि मैं सत्यापन को एक रूप में नहीं रखना चाहता। यह प्रश्न कि किस श्रेणी की संख्या स्वीकार्य है, मॉडल का एक भाग उतना ही है जितना कि यह प्रश्न कि किस प्रकार की संख्या स्वीकार्य है। मैं हर उस फॉर्म के बारे में नहीं बताना चाहता जिसके माध्यम से मॉडल संपादन योग्य है, बस स्वीकार करने के लिए कौन सी संख्या है। यह DRY का उल्लंघन करेगा, और इसके अलावा, यह सिर्फ सादा अनुचित है। इसलिए मैं मॉडल की
सेविंग

tghw, आपने कहा कि मैं "अपवाद को फेंकने या क्षेत्र में जाने वाले डेटा को सीमित करने के लिए मॉडल की बचत विधि को ओवरराइड कर सकता हूं।" मॉडल परिभाषा के ओवरराइड सेव () मेथड के भीतर से मैं - यह कैसे करूँगा कि यदि दर्ज की गई संख्या किसी दिए गए सीमा से बाहर है, तो उपयोगकर्ता को एक सत्यापन त्रुटि प्राप्त होती है जैसे कि उसने एक संख्यात्मक क्षेत्र में वर्ण डेटा दर्ज किया था? Ie वहाँ कुछ तरीका है कि मैं यह कर सकता हूं जो उपयोगकर्ता के व्यवस्थापक के माध्यम से या किसी अन्य रूप से संपादन कर रहा है या नहीं, इस पर ध्यान दिए बिना काम करेगा? मैं केवल उपयोगकर्ता को बताए बिना क्षेत्र में जाने वाले डेटा को सीमित नहीं करना चाहता हूं :) धन्यवाद!
संपाब्लोकपर

यहां तक कि अगर आप विधि "सहेजें", इस अभ्यस्त काम जब MyModel.object.filter तरह क्वेरीसमूह के माध्यम से तालिका अद्यतन करने (blabla) .update (blabla) सहेजें ताकि कोई चेक किया जाएगा फोन नहीं होगा का उपयोग
ओलिवर पोन्स

5

यदि आप कुछ अतिरिक्त लचीलापन चाहते हैं और अपने मॉडल क्षेत्र को बदलना नहीं चाहते तो यहां सबसे अच्छा समाधान है। बस इस कस्टम सत्यापनकर्ता को जोड़ें:

#Imports
from django.core.exceptions import ValidationError      

class validate_range_or_null(object):
    compare = lambda self, a, b, c: a > c or a < b
    clean = lambda self, x: x
    message = ('Ensure this value is between %(limit_min)s and %(limit_max)s (it is %(show_value)s).')
    code = 'limit_value'

    def __init__(self, limit_min, limit_max):
        self.limit_min = limit_min
        self.limit_max = limit_max

    def __call__(self, value):
        cleaned = self.clean(value)
        params = {'limit_min': self.limit_min, 'limit_max': self.limit_max, 'show_value': cleaned}
        if value:  # make it optional, remove it to make required, or make required on the model
            if self.compare(cleaned, self.limit_min, self.limit_max):
                raise ValidationError(self.message, code=self.code, params=params)

और यह इस तरह के रूप में इस्तेमाल किया जा सकता है:

class YourModel(models.Model):

    ....
    no_dependents = models.PositiveSmallIntegerField("How many dependants?", blank=True, null=True, default=0, validators=[validate_range_or_null(1,100)])

दो पैरामीटर अधिकतम और न्यूनतम हैं, और यह नल की अनुमति देता है। यदि आप स्टेटमेंट से छुटकारा चाहते हैं या मॉडल में रिक्त = गलत, अशक्त = गलत हो सकता है, तो आप सत्यापनकर्ता को अनुकूलित कर सकते हैं। निश्चित रूप से प्रवास की आवश्यकता होगी।

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

उम्मीद है कि यह मदद करता है :) Django में Validators पर अधिक ।

पुनश्च। मैं django.core.validators में BaseValidator पर अपना उत्तर आधारित करता हूं, लेकिन कोड को छोड़कर सब कुछ अलग है।

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