python - Django में केस असंवेदनशील अद्वितीय मॉडल फ़ील्ड?




postgresql model (7)

मेरे पास मूल रूप से एक उपयोगकर्ता नाम अद्वितीय है (केस असंवेदनशील), लेकिन उपयोगकर्ता द्वारा प्रदान किए जाने पर प्रदर्शित होने पर मामला मायने रखता है।

मेरी निम्नलिखित ज़रूरतें हैं:

  • फ़ील्ड CharField संगत है
  • क्षेत्र अद्वितीय है, लेकिन मामला असंवेदनशील है
  • फ़ील्ड को खोजे जाने योग्य अनदेखा करने की आवश्यकता होती है (यानी, आसानी से भुलाए जाने वाले आईएक्सएक्ट का उपयोग करने से बचें)
  • फ़ील्ड को अक्षुण्ण रखा जाता है
  • डेटाबेस स्तर पर अधिमानतः लागू किया गया
  • अधिमानतः एक अतिरिक्त क्षेत्र के भंडारण से बचें

क्या यह Django में संभव है?

एकमात्र समाधान जो मैं आया था, वह है "किसी तरह" मॉडल प्रबंधक को ओवरराइड करना, एक अतिरिक्त फ़ील्ड का उपयोग करना, या हमेशा खोज में 'iexact' का उपयोग करना।

मैं Django 1.3 और PostgreSQL 8.4.2 पर हूं।


Answers

चूंकि एक उपयोगकर्ता नाम हमेशा लोअरकेस होता है, इसलिए इसे Django में एक कस्टम लोअरकेस मॉडल फ़ील्ड का उपयोग करने की अनुशंसा की जाती है। एक्सेस और कोड- fields.py की आसानी के लिए, अपने ऐप फ़ोल्डर में एक नई फ़ाइल fields.py बनाएं।

from django.db import models
from django.utils.six import with_metaclass

# Custom lowecase CharField

class LowerCharField(with_metaclass(models.SubfieldBase, models.CharField)):
    def __init__(self, *args, **kwargs):
        self.is_lowercase = kwargs.pop('lowercase', False)
        super(LowerCharField, self).__init__(*args, **kwargs)

    def get_prep_value(self, value):
        value = super(LowerCharField, self).get_prep_value(value)
        if self.is_lowercase:
            return value.lower()
        return value

models.py में उपयोग

from django.db import models
from your_app_name.fields import LowerCharField

class TheUser(models.Model):
    username = LowerCharField(max_length=128, lowercase=True, null=False, unique=True)

अंतिम नोट : आप डेटाबेस में लोअरकेस मानों को संग्रहीत करने के लिए इस विधि का उपयोग कर सकते हैं, और __iexact बारे में चिंता न करें।


आप इसके बजाय citext postgres प्रकार का उपयोग कर सकते हैं और किसी भी प्रकार के iexact के साथ परेशान नहीं कर सकते हैं। बस मॉडल में एक नोट करें कि अंतर्निहित क्षेत्र असंवेदनशील है। बहुत आसान उपाय।


सबसे अच्छा समाधान Django मॉडल फ़ील्ड द्वारा "get_prep_value" को ओवरराइड करना है

class LowerSlugField(models.SlugField):

    def get_prep_value(self, value):
        return str(value).lower()

और फिर:

company_slug = LowerSlugField(max_length=255, unique=True)


Django 1.11 के रूप में, आप CITextField , Citext प्रकार द्वारा समर्थित केस-असंवेदनशील पाठ के लिए पोस्टग्रेज-विशिष्ट फ़ील्ड का उपयोग कर सकते हैं।

from django.db import models
from django.contrib.postgres.fields import CITextField

class Something(models.Model):
    foo = CITextField()

Django CIEmailField और CICharField भी प्रदान करता है, जो CIEmailField और CICharField केस-असंवेदनशील संस्करण हैं।


मूल मिश्रित-केस स्ट्रिंग को एक सादे पाठ कॉलम में संग्रहीत करें । डेटा प्रकार के text उपयोग करें या varchar बिना लंबाई संशोधक के बजाय varchar(n) । वे अनिवार्य रूप से समान हैं, लेकिन varchar (n) के साथ आपको एक मनमाना लंबाई सीमा निर्धारित करनी होगी, यदि बाद में आप बदलना चाहें तो दर्द हो सकता है। इसके बारे में और अधिक पढ़ें मैनुअल में या पीटर Eisentraut @ serverfault.SE द्वारा इस संबंधित उत्तर में

lower(string) पर एक कार्यात्मक अद्वितीय सूचकांक बनाएं। यहाँ प्रमुख बात यह है कि:

CREATE UNIQUE INDEX my_idx ON mytbl(lower(name));

यदि आप एक मिश्रित मामले के नाम को INSERT करने का प्रयास करते हैं जो पहले से ही निचले मामले में है तो आपको एक अद्वितीय कुंजी उल्लंघन त्रुटि मिलती है।
तेजी से समानता खोज के लिए इस तरह एक क्वेरी का उपयोग करें:

SELECT * FROM mytbl WHERE lower(name) = 'foo' --'foo' is lower case, of course.

इंडेक्स में उसी अभिव्यक्ति का उपयोग करें (ताकि क्वेरी योजनाकार संगतता को पहचानता है) और यह बहुत तेज़ होगा।

एक तरफ के रूप में: आप PostgreSQL के अधिक हाल के संस्करण में अपग्रेड करना चाह सकते हैं। 8.4.2 से बहुत सारे महत्वपूर्ण सुधार हुए हैंआधिकारिक Postgres संस्करण साइट पर अधिक।


सामान्य दृष्टिकोण स्ट्रिंग्स या लोअर केस को लुकअप और तुलना के लिए अपरकेस करना है। उदाहरण के लिए:

>>> "hello".upper() == "HELLO".upper()
True
>>> 




python django postgresql model