2011-09-27 4 views
6

एपेंगिन में, मैं एक संपत्ति मूल्य स्वचालित रूप से गणना और ऑब्जेक्ट के साथ संग्रहीत करने की कोशिश कर रहा हूं।एक पायथन ऐप इंजन मॉडल पर put() विधि को ओवरराइट कैसे करें?

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

class Rectangle(db.Model): 
    width = db.IntegerProperty() 
    height = db.IntegerProperty() 
    area = db.IntegerProperty() 

    def put(self, **kwargs): 
     self.area = self.width * self.height 
     super(Rectangle, self).put(**kwargs) 

यह काम करता है जब मैं सीधे क्षेत्र वस्तु पर put() आह्वान:

re1 = Rectangle(width=10, height=10) 
re1.put() 
print re1.area  # >> 10 

लेकिन जब मैं db.put() का उपयोग करता हूं (उदाहरण के लिए उनमें से बहुत से को बचाने के लिए), यह तोड़ता है।

re2 = Rectangle(width=5, height=5) 
db.put(re2) 
print re2.area  # >> None 

गणना मूल्य में 'चुपके' का सही तरीका क्या है?

+0

यदि आप आइटम को डेटाबेस से प्राप्त करते हैं तो आपको क्या मिलता है? क्षेत्र की गणना की जाती है? – rocksportrocker

+0

मैंने डेटास्टोर की जांच की और यह वही कहता है; पहले आयताकार के लिए '10' और दूसरे के लिए 'कोई नहीं'। – Paul

+1

मुझे संदेह है कि 'db.put()' आपकी ऑब्जेक्ट्स पर व्यक्तिगत 'put() 'विधि को कभी भी कॉल नहीं करता है - यह शायद उन्हें डेटाबेस गुणों के लिए निरीक्षण करता है और थोक सम्मिलन विवरण बनाता है। यदि आप 'put' के बजाय' __init__' में क्षेत्र सेट करते हैं, तो क्या होता है? – larsks

उत्तर

7

डालने को ओवरराइड न करें - जैसा कि आप देखते हैं, यह नाजुक है, और यदि आप मॉडल के पुट फ़ंक्शन के बजाय db.put पर कॉल करते हैं तो उसे शामिल नहीं किया जाता है।

सौभाग्य से, अनुप्रयोग इंजन ComputedProperty जो वास्तव में आसानी से अपने यूज-केस बनाता है प्रदान करता है:

class Rectangle(db.Model): 
    width = db.IntegerProperty() 
    height = db.IntegerProperty() 

    @db.ComputedProperty 
    def area(self): 
     return self.width * self.height 
+0

धन्यवाद, यह एक आकर्षण की तरह काम करता है! – Paul

1

मैं मानता हूँ कि ComputedProperty वर्णित विशिष्ट परिदृश्य के लिए जाने का रास्ता है। हालांकि, यह अभी भी put फ़ंक्शन को अधिभारित करने के लिए उपयोगी हो सकता है। उदाहरण के लिए, हम डेटास्टोर लिखने वाले सभी कॉलर्स का ट्रैक रखने के लिए निम्न कोड को नियोजित करते हैं ताकि हम आसानी से लिखने में स्पाइक्स को डिबग कर सकें।

from google.appengine.ext import db 

_orig_db_put_async = db.put_async 
_orig_db_model_put = db.Model.put 

def _new_db_put_async(models, *args, **kwargs): 
    """Instrumented version of db.put_async (which db.put also calls).""" 
    retval = _orig_db_put_async(models, *args, **kwargs) 
    msg = ['query: %s' % _get_caller()] 
    # 'models' can be either a single model instance, or a list of them. 
    try: 
     for model in models: 
      msg.append(model.__class__.__name__ + '.<db.put>') 
    except TypeError: 
     msg.append(models.__class__.__name__ + '.<db.put>') 
    instance_cache.increment(' -- '.join(msg)) 
    return retval 


def _new_db_model_put(self, *args, **kwargs): 
    """Like entity.put() but stores put-stats in the instance cache.""" 
    retval = _orig_db_model_put(self, *args, **kwargs) 
    msg = ['query: %s' % _get_caller()] 
    msg.append(self.__class__.__name__ + '.<put>') 
    instance_cache.increment(' -- '.join(msg)) 
    return retval 

इस कोड को कभी कभी एक गिनती जिनमें से codepaths मेम्कैश में लेखन जारी कर रहे हैं रहता है और फिर लॉग करने के लिए इसे बाहर flushes। लॉग लाइनों कुछ इस तरह दिखाई:

3041: activity_summary.py:312 -- UserData.<put>

कहाँ 3041 समय की संख्या है लाइन activity_summary.py की 312 एक UserData.put() जारी किए हैं।

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