Django 2.1 - Unicode data

यूनिकोड डेटा




django

यूनिकोड डेटा

Django मूल रूप से हर जगह यूनिकोड डेटा का समर्थन करता है। अपने डेटाबेस को प्रदान करना किसी तरह डेटा को स्टोर कर सकता है, आप सुरक्षित रूप से टेम्प्लेट, मॉडल और डेटाबेस के चारों ओर घूम सकते हैं।

यह दस्तावेज़ आपको बताता है कि आपको क्या जानने की आवश्यकता है यदि आप ऐसे एप्लिकेशन लिख रहे हैं जो डेटा या टेम्प्लेट का उपयोग करते हैं जो ASCII के अलावा किसी अन्य चीज़ में एन्कोड किए गए हैं।

डेटाबेस बनाना

सुनिश्चित करें कि आपका डेटाबेस मनमाने स्ट्रिंग डेटा को स्टोर करने में सक्षम होने के लिए कॉन्फ़िगर किया गया है। आम तौर पर, इसका मतलब है कि यह UTF-8 या UTF-16 का एन्कोडिंग है। यदि आप अधिक प्रतिबंधात्मक एन्कोडिंग का उपयोग करते हैं - उदाहरण के लिए, लैटिन 1 (iso8859-1) - आप डेटाबेस में कुछ वर्णों को संग्रहीत करने में सक्षम नहीं होंगे, और जानकारी खो जाएगी।

  • MySQL उपयोगकर्ता, डेटाबेस वर्ण सेट एन्कोडिंग को सेट या परिवर्तित करने के तरीके के विवरण के लिए MySQL मैनुअल का संदर्भ लें।
  • PostgreSQL उपयोगकर्ता, सही एन्कोडिंग के साथ डेटाबेस बनाने के विवरण के लिए PostgreSQL मैनुअल (PostgreSQL 9 में अनुभाग 22.3.2) देखें।
  • ओरेकल उपयोगकर्ता, ओरेकल मैनुअल को संदर्भित करते हैं कि कैसे ( खंड 2 ) सेट करें या ( धारा 11 ) डेटाबेस वर्ण सेट एन्कोडिंग को बदल दें।
  • SQLite उपयोगकर्ता, आपको कुछ भी करने की आवश्यकता नहीं है। आंतरिक कूटबन्धन के लिए SQLite हमेशा UTF-8 का उपयोग करता है।

Django के सभी डेटाबेस का बैकग्राउंड अपने आप डेटाबेस से बात करने के लिए स्ट्रिंग्स को उपयुक्त एन्कोडिंग में बदल देता है। वे डेटाबेस से प्राप्त स्ट्रिंग्स को स्वचालित रूप से स्ट्रिंग्स में भी बदलते हैं। आपको Django को यह बताने की आवश्यकता नहीं है कि आपके डेटाबेस का उपयोग करने वाले एन्कोडिंग क्या है: जो पारदर्शी रूप से नियंत्रित किया जाता है।

अधिक के लिए, नीचे "डेटाबेस एपीआई" अनुभाग देखें।

सामान्य स्ट्रिंग हैंडलिंग

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

चेतावनी

एक bytestring अपने एन्कोडिंग के बारे में इसके साथ कोई जानकारी नहीं रखता है। उस कारण से, हमें एक धारणा बनानी होगी, और Django मान लेता है कि सभी बयाना UTF-8 में हैं।

यदि आप Django के लिए एक स्ट्रिंग पास करते हैं जिसे किसी अन्य प्रारूप में एन्कोड किया गया है, तो चीजें दिलचस्प तरीके से गलत हो जाएंगी। आमतौर पर, Django कुछ बिंदु पर एक UnicodeDecodeError

यदि आपका कोड केवल ASCII डेटा का उपयोग करता है, तो अपने सामान्य तारों का उपयोग करना सुरक्षित है, उन्हें इच्छानुसार पास करना, क्योंकि ASCII UTF-8 का सबसेट है।

यह सोचकर मूर्ख मत बनो कि यदि आपकी DEFAULT_CHARSET सेटिंग 'utf-8' अलावा किसी और चीज़ पर सेट है तो आप उस अन्य एन्कोडिंग का उपयोग अपने बाइटस्टर्क्स में कर सकते हैं! DEFAULT_CHARSET केवल टेम्पलेट रेंडरिंग (और ईमेल) के परिणामस्वरूप उत्पन्न स्ट्रिंग्स पर लागू होता है। Django हमेशा आंतरिक bytestrings के लिए UTF-8 एन्कोडिंग मान जाएगा। इसका कारण यह है कि DEFAULT_CHARSET सेटिंग वास्तव में आपके नियंत्रण में नहीं है (यदि आप एप्लिकेशन डेवलपर हैं)। यह आपके एप्लिकेशन को इंस्टॉल करने और उपयोग करने वाले व्यक्ति के नियंत्रण में है - और यदि वह व्यक्ति एक अलग सेटिंग चुनता है, तो भी आपके कोड को काम करना जारी रखना चाहिए। एर्गो, यह उस सेटिंग पर भरोसा नहीं कर सकता है।

ज्यादातर मामलों में जब Django स्ट्रिंग्स के साथ काम कर रहा है, तो यह कुछ और करने से पहले उन्हें स्ट्रिंग्स में बदल देगा। इसलिए, एक सामान्य नियम के रूप में, यदि आप बाईटस्ट्रिंग में पास होते हैं, तो परिणाम में एक स्ट्रिंग वापस प्राप्त करने के लिए तैयार रहें।

अनूदित तार

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

आम तौर पर, आपको आलसी अनुवादों के बारे में चिंता करने की ज़रूरत नहीं होगी। बस इस बात का ध्यान रखें कि यदि आप किसी वस्तु की जांच करते हैं और यह django.utils.functional.__proxy__ ऑब्जेक्ट होने का दावा करता है, तो यह एक आलसी अनुवाद है। आलसी अनुवाद के साथ str() कॉलिंग तर्क के रूप में वर्तमान लोकेल में एक स्ट्रिंग उत्पन्न करेगा।

आलसी अनुवाद वस्तुओं के बारे में अधिक जानकारी के लिए, internationalization प्रलेखन का संदर्भ लें।

उपयोगी उपयोगिता कार्य

चूँकि कुछ स्ट्रिंग ऑपरेशन बार-बार आते हैं, Django कुछ उपयोगी कार्यों के साथ है जो स्ट्रिंग और बाइटस्ट्रिंग ऑब्जेक्ट के साथ काम करना आसान बना देता है।

रूपांतरण कार्य

django.utils.encoding मॉड्यूल में कुछ फ़ंक्शंस होते हैं जो स्ट्रिंग्स और बाइटस्ट्रेस के बीच आगे और पीछे परिवर्तित करने के लिए आसान होते हैं।

  • smart_text(s, encoding='utf-8', strings_only=False, errors='strict') इसके इनपुट को एक स्ट्रिंग में परिवर्तित करता है। encoding पैरामीटर इनपुट एन्कोडिंग को निर्दिष्ट करता है। (उदाहरण के लिए, Django इस का उपयोग आंतरिक रूप से करता है जब प्रसंस्करण फॉर्म इनपुट डेटा, जो कि UTF-8 एन्कोडेड नहीं हो सकता है।) strings_only पैरामीटर, यदि सही पर सेट किया गया है, तो पायथन संख्या, बूलियन और None स्ट्रिंग में परिवर्तित नहीं किया जाएगा (वे उनके मूल प्रकार को रखना)। errors पैरामीटर में से कोई भी मान लेता है जिसे पायथन के str() फ़ंक्शन द्वारा स्वीकार किया जाता है।
  • force_text(s, encoding='utf-8', strings_only=False, errors='strict') लगभग सभी मामलों में smart_text() समान है। अंतर तब है जब पहला तर्क एक आलसी अनुवाद का उदाहरण है। जबकि smart_text() आलसी अनुवादों को संरक्षित करता है, force_text() उन वस्तुओं को एक स्ट्रिंग के लिए मजबूर करता है (अनुवाद होने के कारण)। आम तौर पर, आप smart_text() का उपयोग करना चाहेंगे। हालाँकि, force_text() टेम्प्लेट टैग और फिल्टरों में उपयोगी है, force_text() साथ काम करने के लिए एक स्ट्रिंग होनी चाहिए , न कि केवल कुछ जिसे स्ट्रिंग में बदला जा सके।
  • smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict') अनिवार्य रूप से smart_text() के विपरीत है। यह पहले तर्क को बाइटस्ट्रिंग के लिए मजबूर करता है। strings_only पैरामीटर में smart_text() और force_text() के समान व्यवहार है। यह पायथन के बिलिन str() फ़ंक्शन से थोड़ा अलग शब्दार्थ है, लेकिन Django के इंटर्नल के भीतर कुछ स्थानों पर अंतर की आवश्यकता है।

आम तौर पर, आपको केवल force_text() का उपयोग force_text() । इसे किसी भी इनपुट डेटा पर जितनी जल्दी हो सके कॉल करें, जो या तो एक स्ट्रिंग या बायस्ट्रिंग हो सकता है, और तब से, आप परिणाम को हमेशा एक स्ट्रिंग के रूप में मान सकते हैं।

यूआरआई और आईआरआई हैंडलिंग

वेब फ्रेमवर्क को यूआरएल (जो IRI का एक प्रकार है) से निपटना पड़ता है। URL की एक आवश्यकता यह है कि वे केवल ASCII वर्णों का उपयोग करके एन्कोड किए गए हैं। हालाँकि, एक अंतर्राष्ट्रीय वातावरण में, आपको एक IRI से एक URL बनाने की आवश्यकता हो सकती है - बहुत ही कम बोलने वाला, एक URI जिसमें यूनिकोड वर्ण शामिल हो सकते हैं। IRI को URI में बदलने और परिवर्तित करने के लिए इन कार्यों का उपयोग करें:

फ़ंक्शंस के इन दो समूहों में कुछ अलग उद्देश्य हैं, और उन्हें सीधे रखना महत्वपूर्ण है। आम तौर पर, आप आईआरआई या यूआरआई पथ के अलग-अलग हिस्सों पर quote() उपयोग करेंगे ताकि किसी भी आरक्षित वर्ण जैसे 'और' या '%' सही ढंग से एन्कोड किए गए हों। फिर, आप iri_to_uri() को पूर्ण IRI पर लागू iri_to_uri() और यह किसी भी गैर-ASCII वर्णों को सही एन्कोडेड मानों में परिवर्तित करता है।

ध्यान दें

तकनीकी रूप से, यह कहना सही नहीं है कि iri_to_uri() IRI विनिर्देशन में पूर्ण एल्गोरिथ्म को लागू करता है। यह (अभी तक) एल्गोरिथ्म के अंतर्राष्ट्रीय डोमेन नाम एन्कोडिंग भाग को प्रदर्शित नहीं करता है।

iri_to_uri() फ़ंक्शन ASCII वर्णों को नहीं बदलेगा जो किसी URL में अन्यथा अनुमत हैं। इसलिए, उदाहरण के लिए, जब iri_to_uri() को पास किया जाता है, तो चरित्र '%' आगे एन्कोडेड नहीं होता है। इसका मतलब है कि आप इस फ़ंक्शन के लिए एक पूर्ण URL पास कर सकते हैं और यह क्वेरी स्ट्रिंग या ऐसा कुछ भी गड़बड़ नहीं करेगा।

एक उदाहरण यहाँ चीजों को स्पष्ट कर सकता है:

>>> from urllib.parse import quote
>>> from django.utils.encoding import iri_to_uri
>>> quote('Paris & Orléans')
'Paris%20%26%20Orl%C3%A9ans'
>>> iri_to_uri('/favorites/François/%s' % quote('Paris & Orléans'))
'/favorites/Fran%C3%A7ois/Paris%20%26%20Orl%C3%A9ans'

यदि आप ध्यान से देखें, तो आप देख सकते हैं कि quote() द्वारा दूसरे भाग में उत्पन्न किया गया हिस्सा iri_to_uri() पारित होने पर दोहरे-उद्धृत नहीं किया गया था। यह एक बहुत ही महत्वपूर्ण और उपयोगी सुविधा है। इसका अर्थ है कि आप अपने IRI का निर्माण इस बात की परवाह किए बिना कर सकते हैं कि इसमें गैर-ASCII वर्ण हैं और फिर, दाईं ओर, परिणाम पर iri_to_uri() कॉल करें।

इसी प्रकार, Django django.utils.encoding.uri_to_iri() प्रदान करता है जो RFC 3987 # अनुभाग-3.2 के अनुसार URI से IRI में रूपांतरण लागू करता है।

एक उदाहरण प्रदर्शित करने के लिए:

>>> from django.utils.encoding import uri_to_iri
>>> uri_to_iri('/%E2%99%A5%E2%99%A5/?utf8=%E2%9C%93')
'/♥♥/?utf8=✓'
>>> uri_to_iri('%A9hello%3Fworld')
'%A9hello%3Fworld'

पहले उदाहरण में, UTF-8 वर्ण अयोग्य हैं। दूसरे में, प्रतिशत-एनकोडिंग अपरिवर्तित रहते हैं क्योंकि वे वैध UTF-8 रेंज के बाहर स्थित होते हैं या आरक्षित वर्ण का प्रतिनिधित्व करते हैं।

दोनों iri_to_uri() और uri_to_iri() फ़ंक्शंस idempotent हैं, जिसका अर्थ है कि निम्नलिखित हमेशा निम्न हैं:

iri_to_uri(iri_to_uri(some_string)) == iri_to_uri(some_string)
uri_to_iri(uri_to_iri(some_string)) == uri_to_iri(some_string)

तो आप सुरक्षित रूप से एक ही URI / IRI पर कई बार कॉल कर सकते हैं बिना डबल-क्विटिंग समस्याओं के जोखिम के।

मॉडल के

क्योंकि सभी स्ट्रिंग्स को डेटाबेस से स्ट्रिंग ऑब्जेक्ट्स के रूप में लौटाया जाता है, मॉडल फ़ील्ड जो चरित्र आधारित हैं (CharField, TextField, URLField, आदि) में यूनिकोड मान शामिल होगा जब Django डेटाबेस से डेटा पुनर्प्राप्त करता है। यह हमेशा मामला होता है, भले ही डेटा एक ASCII बाइटिंग में फिट हो सके।

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

get_absolute_url() में ध्यान रखना

URL में केवल ASCII वर्ण हो सकते हैं। यदि आप डेटा के टुकड़ों से एक URL का निर्माण कर रहे हैं जो गैर-ASCII हो सकता है, तो परिणामों को इस तरह से एनकोड करने के लिए सावधान रहें जो URL के लिए उपयुक्त है। reverse() फ़ंक्शन आपके लिए यह स्वचालित रूप से संभालता है।

यदि आप मैन्युअल रूप से एक URL का निर्माण कर रहे हैं (यानी, reverse() फ़ंक्शन का उपयोग नहीं कर रहे हैं), तो आपको स्वयं एन्कोडिंग का ध्यान रखना होगा। इस स्थिति में, iri_to_uri() और quote() फ़ंक्शन का उपयोग करें जो above दस्तावेज किए गए थे। उदाहरण के लिए:

from urllib.parse import quote
from django.utils.encoding import iri_to_uri

def get_absolute_url(self):
    url = '/person/%s/?x=0&y=0' % quote(self.location)
    return iri_to_uri(url)

यह फ़ंक्शन सही ढंग से एन्कोडेड URL लौटाता है, भले ही self.location कुछ ऐसा हो जैसे "जैक पेरिस और ऑरलियन्स का दौरा किया"। (वास्तव में, iri_to_uri() कॉल उपरोक्त उदाहरण में कड़ाई से आवश्यक नहीं है, क्योंकि सभी गैर-ASCII वर्ण पहली पंक्ति में उद्धृत किए गए हैं।)

डेटाबेस एपीआई

आप या तो स्ट्रिंग या यूटीएफ -8 बाइटस्ट्रेस को filter() विधियों और डेटाबेस एपीआई में पसंद के रूप में पारित कर सकते हैं। निम्नलिखित दो क्वेरी समान हैं:

qs = People.objects.filter(name__contains='Ã…')
qs = People.objects.filter(name__contains=b'\xc3\x85') # UTF-8 encoding of Ã…

टेम्पलेट्स

मैन्युअल रूप से टेम्प्लेट बनाते समय आप स्ट्रिंग्स या UTF-8 बायस्ट्रेस का उपयोग कर सकते हैं:

from django.template import Template
t1 = Template(b'This is a bytestring template.')
t2 = Template('This is a string template.')

लेकिन सामान्य मामला फाइलसिस्टम से टेम्प्लेट पढ़ने का है, और इससे थोड़ी जटिलता पैदा होती है: सभी फाइल सिस्टम यूटीएफ -8 के रूप में एन्कोडेड अपने डेटा को स्टोर नहीं करते हैं। यदि आपकी टेम्प्लेट फाइलें UTF-8 एन्कोडिंग के साथ संग्रहीत नहीं हैं, तो FILE_CHARSET सेटिंग को डिस्क पर फ़ाइलों के एन्कोडिंग पर सेट करें। जब Django एक टेम्पलेट फ़ाइल में पढ़ता है, तो यह इस एन्कोडिंग से डेटा को यूनिकोड में बदल देगा। ( FILE_CHARSET डिफ़ॉल्ट रूप से 'utf-8' सेट है)

DEFAULT_CHARSET सेटिंग प्रदान किए गए टेम्प्लेट के एन्कोडिंग को नियंत्रित करती है। यह डिफ़ॉल्ट रूप से UTF-8 पर सेट है।

टेम्प्लेट टैग और फ़िल्टर

अपने स्वयं के टेम्प्लेट टैग और फ़िल्टर लिखते समय याद रखने के लिए कुछ सुझाव:

  • हमेशा टेम्प्लेट टैग के render() विधि से और टेम्प्लेट फ़िल्टर से स्ट्रिंग्स लौटाएं।
  • इन स्थानों में force_text() को प्राथमिकता में force_text() उपयोग करें। टेम्प्लेट रेंडर किए जाने के बाद टैग रेंडरिंग और फिल्टर कॉल होते हैं, इसलिए आलसी अनुवाद ऑब्जेक्ट्स को स्ट्रिंग्स में परिवर्तित करने से कोई फायदा नहीं है। उस बिंदु पर तार के साथ पूरी तरह से काम करना आसान है।

फ़ाइलें

यदि आप उपयोगकर्ताओं को फ़ाइलें अपलोड करने की अनुमति देने का इरादा रखते हैं, तो आपको यह सुनिश्चित करना होगा कि Django चलाने के लिए उपयोग किए जाने वाले वातावरण को गैर-ASCII फ़ाइल नामों के साथ काम करने के लिए कॉन्फ़िगर किया गया है। यदि आपका वातावरण सही तरीके से कॉन्फ़िगर नहीं किया गया है, तो गैर-ASCII वर्णों वाली फ़ाइल नामों के साथ फ़ाइलों को सहेजते समय आप UnicodeEncodeError अपवादों का सामना करेंगे।

UTF-8 फ़ाइल नामों के लिए फ़ाइल सिस्टम समर्थन बदलता है और पर्यावरण पर निर्भर हो सकता है। चल रहे द्वारा एक इंटरैक्टिव पायथन शेल में अपने वर्तमान विन्यास की जाँच करें:

import sys
sys.getfilesystemencoding()

यह आउटपुट "UTF-8" होना चाहिए।

LANG पर्यावरण चर Unix प्लेटफार्मों पर अपेक्षित एन्कोडिंग की स्थापना के लिए जिम्मेदार है। इस चर को सेट करने के लिए उपयुक्त सिंटैक्स और स्थान के लिए अपने ऑपरेटिंग सिस्टम और एप्लिकेशन सर्वर के लिए प्रलेखन से परामर्श करें।

अपने विकास के माहौल में, आपको अपने ~.bashrc अनुरूप के लिए एक सेटिंग जोड़ने की आवश्यकता हो सकती है ::

export LANG="en_US.UTF-8"

फार्म जमा करना

HTML फॉर्म सबमिशन एक ट्रिकी एरिया है। इस बात की कोई गारंटी नहीं है कि सबमिशन में एन्कोडिंग जानकारी शामिल होगी, जिसका अर्थ है कि रूपरेखा प्रस्तुत डेटा के एन्कोडिंग पर अनुमान लगा सकती है।

Django फॉर्म डेटा को डिकोड करने के लिए "आलसी" दृष्टिकोण अपनाता है। जब आप इसे एक्सेस करते हैं तो HttpRequest ऑब्जेक्ट में डेटा केवल डिकोड किया जाता है। वास्तव में, अधिकांश डेटा को डिकोड नहीं किया जाता है। केवल HttpRequest.GET और HttpRequest.POST डेटा संरचनाओं में उनके लिए कोई डिकोडिंग लागू है। वे दो क्षेत्र अपने सदस्यों को यूनिकोड डेटा के रूप में वापस करेंगे। HttpRequest की अन्य सभी विशेषताएँ और विधियाँ डेटा को ठीक उसी तरह HttpRequest हैं, जैसा कि ग्राहक द्वारा प्रस्तुत किया गया था।

डिफ़ॉल्ट रूप से, DEFAULT_CHARSET सेटिंग का उपयोग प्रपत्र डेटा के लिए एन्कोडिंग एन्कोडिंग के रूप में किया जाता है। यदि आपको इसे किसी विशेष रूप में बदलने की आवश्यकता है, तो आप HttpRequest उदाहरण पर encoding विशेषता सेट कर सकते हैं। उदाहरण के लिए:

def some_view(request):
    # We know that the data must be encoded as KOI8-R (for some reason).
    request.encoding = 'koi8-r'
    ...

एक्सेस किए गए request.GET बाद आप एन्कोडिंग को भी बदल सकते हैं। request.GET या request.POST , और उसके बाद के सभी एक्सेस नए एन्कोडिंग का उपयोग करेंगे।

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

Django फ़ाइल अपलोड के डेटा को डीकोड नहीं करता है, क्योंकि उस डेटा को आमतौर पर बाइट्स के संग्रह के रूप में माना जाता है, बजाय स्ट्रिंग्स के। किसी भी स्वचालित डिकोडिंग से बाइट्स की धारा का अर्थ बदल जाएगा।