जानकारी लॉगिंग करते समय get_FOO_display() पूर्णांक मान क्यों देता है (django)?जानकारी लॉगिंग करते समय get_FOO_display() पूर्णांक मान क्यों देता है (django)?
मेरे पास एक मॉडल फ़ील्ड है जो इसके मूल्य को प्रतिबंधित करने के लिए एक विकल्प का उपयोग कर रहा है। यह ठीक काम करता है और मैं इसे ऐप के भीतर हर जगह काम कर रहा हूं, लॉगिंग जानकारी को छोड़कर, जब get_FOO_display() विधि मानव-पठनीय संस्करण के के बजाय अंतर्निहित पूर्णांक मान देता है।
यह मॉडल परिभाषा (संक्षिप्त) है:
THING_ROLE_MONSTER = 0
THING_ROLE_MUMMY = 1
ROLE_CHOICES = (
(THING_ROLE_MONSTER, u'Monster'),
(THING_ROLE_MUMMY, u'Mummy'),
)
# definition of property within model
class Thing(models.Model):
...
role = models.IntegerField(
'Role',
default=0,
choices=ROLE_CHOICES
)
अगर मैं (Django) इंटरैक्टिव खोल यह वास्तव में बर्ताव करता है के रूप में आप उम्मीद करेंगे के भीतर इस चलाएँ:
>>> from frankenstein.core.models import Thing
>>> thing = Thing()
>>> thing.role = 0
>>> thing.get_role_display()
u'Monster'
हालांकि, जब मैं स्ट्रिंग स्वरूपण/लॉगिंग परिदृश्य में बिल्कुल उसी निर्माण का उपयोग करता हूं तो मुझे समस्या मिलती है:
logger.info('New thing: <b>%s</b>', thing.get_role_display())
रिटर्न:
New thing: <b>0</b>
मदद!
[अद्यतन 1]
जब मैं इंटरैक्टिव खोल मैं सही आउटपुट प्राप्त भीतर प्रवेश चलाएँ:
>>> from frankenstein.core.models import Thing
>>> import logging
>>> thing = Thing()
>>> thing.role = 0
>>> logging.info('hello %s', b.get_role_display())
INFO hello Monster
[अद्यतन 2] Django internals
से जवाब पर बाद @ joao-oliveira नीचे, मैंने आंतरिक में खोला है और निम्नलिखित को उजागर किया है।
django.db.models
में अंतर्निहित _get_FIELD_display विधि इस प्रकार है:
def _get_FIELD_display(self, field):
value = getattr(self, field.attname)
return force_unicode(dict(field.flatchoices).get(value, value), strings_only=True)
अगर मैं कोड में एक ब्रेकपाइंट डाल दिया, और फिर ipdb चलाने मैं देख सकता हूँ कि मैं मुद्दा है:
ipdb> thing.get_role_display()
u'1'
ipdb> thing._get_FIELD_display(thing._meta.get_field('role'))
u'1'
तो, फिक्स ने कुछ भी नहीं बदला है। अगर मैं तो हाथ से _get_FIELD_display
विधि कोड के माध्यम से चलाने की कोशिश करें, मैं इस मिल:
ipdb> fld = thing._meta.get_field('role')
ipdb> fld.flatchoices
[(0, 'Monster'), (1, 'Mummy')]
ipdb> getattr(thing, fld.attname)
u'1'
ipdb> value = getattr(thing, fld.attname)
ipdb> dict(fld.flatchoices).get(value, value)
u'1'
कौन सा बराबर है कह रहे हैं:
ipdb> {0: 'Monster', 1: 'Mummy'}.get(u'1', u'1')
u'1'
So. हमारे पास समस्या यह है कि विधि विकल्प शब्दकोश में संबंधित विवरण देखने के लिए स्ट्रिंग मान u'1'
का उपयोग कर रहा है, लेकिन शब्दकोश कुंजी पूर्णांक हैं, और स्ट्रिंग नहीं हैं। इसलिए हम कभी भी एक मैच नहीं प्राप्त करते हैं, बल्कि इसके बजाय डिफ़ॉल्ट मान, जो मौजूदा मान (स्ट्रिंग) पर सेट होता है।
मैं मैन्युअल रूप से int करने के लिए कलाकारों के लिए मजबूर हैं, कोड काम करता है के रूप में उम्मीद:
ipdb> dict(fld.flatchoices).get(int(value), value)
'Mummy'
ipdb> print 'w00t'
यह सब बहुत अच्छा है, लेकिन क्यों get_foo_display विधि करता लौट के रूप में अपने मूल प्रश्न का उत्तर न अधिकांश समय सही मूल्य। किसी बिंदु पर स्ट्रिंग (u'1 ') को सही डेटा प्रकार (1) पर डाला जाना चाहिए।
[अद्यतन 3] जवाब
जबकि एक सम्मानजनक उल्लेख उसके अंतर्दृष्टि के लिए जोआओ के पास जाना चाहिए, इनाम कुंद तथ्य यह है कि मैं गलत मूल्य में गुजर रहा शुरू करने के लिए उनका कहना है के लिए जोश करने जा रहा है साथ में। मैंने इसे 'दृढ़ता से टाइप की गई दुनिया' से एक इमिग्रेट करने के लिए रखा, जहां ये चीजें नहीं हो सकतीं!
कोड जो मैंने यहां शामिल नहीं किया है वह यह है कि cleaned_data
ChoiceField से ऑब्जेक्ट को डीजेंगो फॉर्म से शुरू किया गया है। इसके साथ समस्या यह है कि चॉइसफ़िल्ल्ड का आउटपुट एक स्ट्रिंग है, पूर्णांक नहीं। मुझे जो कुछ याद आया वह यह है कि एक कमजोर भाषा में एक स्ट्रिंग के साथ एक पूर्णांक संपत्ति सेट करना संभव है, और कुछ भी बुरा नहीं होने के लिए।
अब यह देखने के बाद, मुझे लगता है कि cleaned_data
से आउटपुट हमेशा एक पूर्णांक है, मुझे यह सुनिश्चित करने के लिए TypedChoiceField का उपयोग करना चाहिए था।
सभी को धन्यवाद।
स्पष्ट होने के लिए, क्या यह फ़ाइल में लॉगिंग है, या किसी सेवा में लॉगिंग कर रहा है (उदाहरण के लिए, हिपचैट)? आईआईआरसी, लॉगर आलसी मूल्यांकन करता है, और वास्तव में get_FOO_display –
का मूल्यांकन करने के लिए एक सेवा कॉल 'पर्याप्त' पर विचार नहीं कर सकता है, यह अनुरोधों का उपयोग करके HTTP पर एक सेवा पर लॉग ऑन कर रहा है। –
कोड यहां है - https://gist.github.com/3176710 –