2012-11-12 3 views
6

जानकारी लॉगिंग करते समय 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_dataChoiceField से ऑब्जेक्ट को डीजेंगो फॉर्म से शुरू किया गया है। इसके साथ समस्या यह है कि चॉइसफ़िल्ल्ड का आउटपुट एक स्ट्रिंग है, पूर्णांक नहीं। मुझे जो कुछ याद आया वह यह है कि एक कमजोर भाषा में एक स्ट्रिंग के साथ एक पूर्णांक संपत्ति सेट करना संभव है, और कुछ भी बुरा नहीं होने के लिए।

अब यह देखने के बाद, मुझे लगता है कि cleaned_data से आउटपुट हमेशा एक पूर्णांक है, मुझे यह सुनिश्चित करने के लिए TypedChoiceField का उपयोग करना चाहिए था।

सभी को धन्यवाद।

+0

स्पष्ट होने के लिए, क्या यह फ़ाइल में लॉगिंग है, या किसी सेवा में लॉगिंग कर रहा है (उदाहरण के लिए, हिपचैट)? आईआईआरसी, लॉगर आलसी मूल्यांकन करता है, और वास्तव में get_FOO_display –

+0

का मूल्यांकन करने के लिए एक सेवा कॉल 'पर्याप्त' पर विचार नहीं कर सकता है, यह अनुरोधों का उपयोग करके HTTP पर एक सेवा पर लॉग ऑन कर रहा है। –

+0

कोड यहां है - https://gist.github.com/3176710 –

उत्तर

11

मैं सच में माफी चाहता हूँ: क्यों you'r कि उत्पादन हो रही

_get_FIELD_display बुला की कोशिश ऑनडस्केंडिंग, लेकिन क्या आप 100% सुनिश्चित हैं कि आप मान को पूर्णांक 1 पर सेट कर रहे हैं और स्ट्रिंग '1' नहीं?

मैं आंतरिक के माध्यम से डाइविंग चला गया हूं और कुछ परीक्षण चला रहा हूं और एकमात्र तरीका यह है कि आप जिस समस्या का सामना कर रहे हैं, वह समझ में आता है कि यदि आप एक स्ट्रिंग को मान सेट कर रहे हैं।

>>> from flogger.models import TestUser 
>>> t = TestUser() 
>>> t.status = 1 
>>> t.get_status_display() 
u'Admin' 
>>> t.status = '1' 
>>> t.get_status_display() 
u'1' 

आपके विचार कोड की जाँच करें, या जो कुछ भी कोड वास्तव में मूल्य स्थापित कर रही है, और सीधे मैदान के आउटपुट का परीक्षण: मेरे सरल यहां परीक्षण देखें।

आप आंतरिक मॉडल कोड से चिपकाया के रूप में:

def _get_FIELD_display(self, field): 
    value = getattr(self, field.attname) 
    return force_unicode(dict(field.flatchoices).get(value, value), strings_only=True) 

यह बस शब्दकोश में क्षेत्र के वर्तमान मूल्य हो जाता है, और अनुक्रमित, और विशेषता के मान लौटाता है यदि एक देखने नहीं मिला है ।

मुझे लगता है कि पहले कोई त्रुटि नहीं थी, क्योंकि मान डेटाबेस में डालने से पहले एक पूर्णांक में घुमाया गया है।

संपादित करें:

अपने अद्यतन अजगर के प्रकार प्रणाली उल्लेख के बारे में

। सबसे पहले, यह सुनिश्चित करने के लिए कि फॉर्म आपके द्वारा अपेक्षित प्रकार की पुष्टि करता है, आपको TypedChoiceField का उपयोग करना चाहिए। दूसरा, पायथन एक दृढ़ता से टाइप की गई भाषा है, लेकिन IntegerField डाटाबेस की तैयारी करते समय int() के साथ अपनी स्वयं की कॉर्सिंग करता है।

चर टाइप नहीं किए गए हैं, लेकिन उनके भीतर के मूल्य हैं। मैं वास्तव में हैरान था कि IntegerField एक int को भी स्ट्रिंग को मजबूर कर रहा था। यहां सीखने के लिए अच्छा सबक - मूल बातें पहले जांचें!

+0

बिल्कुल संकोच नहीं कर रहा है - मैं बस इस सटीक विषय पर दोबारा पोस्ट करने वाला था - क्योंकि इसके माध्यम से चीजों का पता लगाना बिल्कुल ठीक हो रहा है। मैं मान सेट करने के लिए form.cleaned_data का उपयोग कर रहा हूं, और यह स्ट्रिंग का उपयोग किया जाता है, पूर्णांक नहीं। –

+0

@ ह्यूगोरोजर-ब्राउन खुश हैं कि आप वहां पहुंचे हैं, हालांकि पाइथन की प्रकार प्रणाली के बारे में मेरे संपादन को पढ़ने के लायक हो सकते हैं। –

+0

जोश, आपने आज मेरे गधे को बचाया! बहुत सारे से बहुत धन्यवाद – doniyor

0

इस प्रयास करें:

class Thing(models.Model): 

    THING_ROLE_MONSTER = 0 
    THING_ROLE_MUMMY = 1 

    ROLE_CHOICES = (
     (THING_ROLE_MONSTER, u'Monster'), 
     (THING_ROLE_MUMMY, u'Mummy'), 
    ) 

    role = models.IntegerField('Role', default=0,choices=ROLE_CHOICES) 
+0

यह मेरे लिए कुछ भी अलग नहीं करता है। मैंने django internals में गहरे गोताखोरी के बाद प्रश्न में एक अद्यतन पोस्ट किया है। –

2

अपने कोड की कोशिश की है नहीं, न तो @ तरह-यह खेद का जवाब है, लेकिन _get_FIELD_display models.Model से get_Field_display समारोह सेट करने के लिए खेतों में curried है, इसलिए thats शायद इस लगता है अगर ग

logging.info('hello %s', b._get_FIELD_display(b._meta.get('role'))) 
+0

मैंने _meta.get_field ('role') का उपयोग करने के लिए इसे थोड़ा सा बदल दिया है .get() काम नहीं करता है। हालांकि, अभी भी वही परिणाम मिलता है - प्रदर्शन नाम के बजाए अंतर्निहित पूर्णांक। –

+0

मैंने आपके उत्तर से निम्नलिखित में एक अपडेट पोस्ट किया है। मैंने आपका जवाब भी चुना है, क्योंकि यह वास्तव में सहायक रहा है, हालांकि मैंने इसे 'उत्तर' के रूप में चिह्नित नहीं किया है क्योंकि समस्या अभी भी मौजूद है। –

+0

मुझे खेद है, मुझे कुछ और नहीं मिला है, और मैंने आपका पूरा कोड नहीं पढ़ा है, लेकिन अगर यह प्रतिलिपि पर काम करता है तो यह आपके फ़ाइल कोड होना चाहिए, जिससे आप कार्य को विकसित कर सकते हैं और लॉग आउट करने के लिए अपना आउटपुट दे सकते हैं। व्यवहार वही होना चाहिए जो मुझे लगता है कि – jxs

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