2012-08-23 15 views
13

मैं db.Model से ndb.Model पर माइग्रेशन की प्रक्रिया में हूं। इस माइग्रेशन को समाप्त करने से पहले मुझे हल करने का एकमात्र मुद्दा यह है कि Model.is_saved विधि नहीं है। मैं संस्थाओं आदिक्या डेटाडेटोर में मॉडल लगातार है या नहीं, तो एनडीबी के साथ निर्धारित करना संभव है?

प्रलेखन कहते हैं ndb.Modelis_saved विधि के लिए कोई समकक्ष है कि बनाने पर विरोध हुआ चाबी के लिए जाँच करने के लिए अपने आवेदन में db.Model.is_saved का इस्तेमाल किया है निर्धारित करने के लिए sharded काउंटरों put/delete पर अद्यतन किया जाना चाहिए अगर,। मैं के बजाय get_or_insert के साथ कुछ उपयोग मामलों को फिर से कार्यान्वित कर सकता हूं। पर उनमें से सभी नहीं।

एक गंदे हैक के रूप में मैं कन्स्ट्रक्टर को कॉल करके बनाए गए हर उदाहरण के लिए _in_memory_instance जैसे ध्वज सेट कर सकता हूं। लेकिन यह मेरी समस्या का समाधान नहीं करता है। मुझे अभी भी प्रत्येक put() कॉल के बाद कम से कम इस ध्वज को अपडेट करना होगा।

सवाल यह है कि क्या यह निर्धारित करने का बेहतर तरीका है कि मॉडल डेटास्टोर में लगातार है या नहीं, अतिरिक्त डेटास्टोर हिट के बिना?

संपादित करें 1: उल्लेख करने के लिए भूल गए: सभी इकाइयों को कुंजी मिल गई है इसलिए Model._has_complete_key() मेरे लिए काम नहीं करता है।

संपादित करें 2: इस चर्चा के बाद https://groups.google.com/d/topic/google-appengine/Tm8NDWIvc70/discussion यह मेरी समस्या का समाधान करने का एकमात्र तरीका है _post_get_hook/_post_put_hook का उपयोग करना। मैं सोच रहा हूं कि आधिकारिक एपीआई में ऐसी छोटी सी चीज़ क्यों शामिल नहीं थी।

संपादित करें 3: मैं अपने सभी मॉडलों के लिए अगले बेस क्लास के साथ समाप्त हुआ। @Tim Hoffmans विचार के आधार पर

class BaseModel(ndb.Model): 

    @classmethod 
    def _post_get_hook(cls, key, future): 
     self = future.get_result() 
     if self: 
      self._is_saved = bool(key) 

    def _post_put_hook(self, future): 
     self._is_saved = future.state == future.FINISHING 

    def is_saved(self): 
     if self._has_complete_key(): 
      return getattr(self, "_is_saved", False) 
     return False 
+0

क्या आप यह जांच सकते हैं कि ऑब्जेक्ट में वास्तव में कोई कुंजी/आईडी है या नहीं? (संभवतः एक कोशिश/खंड को छोड़कर)। एनडीबी मॉडल वर्ग से परिचित नहीं है, लेकिन मुझे याद है कि डीबी.मोडेल एक त्रुटि उठाता है (या कोई नहीं देता है?) यदि आप सहेजने से पहले मॉडल उदाहरण की आईडी/कुंजी प्राप्त करने का प्रयास करते हैं (या संभवतः यह 'कोई नहीं' लौटाता है)। ऐसा मत सोचो कि डेटास्टोर हिट के साथ खत्म हो जाएगा। यदि यह काम करता है, तो आप केवल एक ऐसी संपत्ति लिख सकते हैं जो 'def is_saved (self) जैसा है: वापस self.key() कोई नहीं है (या इसे एक कोशिश/निकालने के साथ करें जो एक अपवाद उठाया गया है और अन्यथा झूठा है)। –

+0

कुंजी की जांच करने से कोई काम नहीं होने पर काम नहीं करेगा। एक संभावित विकल्प (लेकिन अपर्याप्त हो सकता है) में creat_date ध्वज है (auto_now_add = True पर सेट करें)। दस्तावेज़ों से "स्वचालित मान तब तक उत्पन्न नहीं होता है जब तक कि इकाई लिखी नहीं जाती है, यानी, ये विकल्प डायनामिक डिफ़ॉल्ट प्रदान नहीं करते हैं।" हालांकि अगर लेखन विफल रहता है तो मान निर्धारित किया जाएगा। यद्यपि आपको पता होना चाहिए कि लेखन विफल रहा है ;-) –

+1

वैकल्पिक रूप से _post_put_hook का उपयोग अपने ध्वज को इंगित करने के लिए करते हुए इंगित करता है कि यह सहेजा गया था। –

उत्तर

11

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

class Employee(ndb.Model): 
    <properties here> 

    saved = False # class variable provides default value 

    @classmethod 
    def _post_get_hook(cls, key, future): 
    obj = future.get_result() 
    if obj is not None: 
     # test needed because post_get_hook is called even if get() fails! 
     obj.saved = True 

    def _post_put_hook(self, future): 
    self.saved = True 

भविष्य की स्थिति की जांच करने के कोई ज़रूरत नहीं है: यहाँ एक काम उदाहरण है। ऐसा इसलिए है क्योंकि हुक वास्तव में भविष्य में एक कॉलबैक है। हालांकि की आवश्यकता है जांचें कि इसका परिणाम कोई नहीं है!

पीएस: एक लेनदेन के अंदर, हुक को पुट() कॉल रिटर्न के रूप में जल्द ही बुलाया जाता है; लेनदेन की सफलता या विफलता उन्हें प्रभावित नहीं करती है। एक सफल प्रतिबद्धता के बाद एक हुक चलाने के लिए https://developers.google.com/appengine/docs/python/ndb/contextclass#Context_call_on_commit देखें।

+5

जैसा कि चर्चा की गई [यहां] (https://code.google.com/p/appengine-ndb-experiment/issues/detail?id=211) यह ट्रस्ट क्वेरी/gql पुनर्प्राप्त इकाइयों के लिए काम नहीं करेगा क्योंकि _post_get_hook नहीं है उनसे कहा जाता है और प्रश्नों के लिए कोई समकक्ष कॉलबैक नहीं है (अभी तक)। –

2

आप आप एक पोस्ट हुक इसलिए की तरह कर सकते हैं:: अब मैं अपने codebase छोड़ सकते हैं (लगभग) अछूता

class Article(ndb.Model): 
    title = ndb.StringProperty() 

    is_saved = False 

    def _post_put_hook(self, f): 
     if f.state == f.FINISHING: 
      self.is_saved = True 
     else: 
      self.is_saved = False 


article = Article() 
print article.is_saved ## False 
article.put() 
print article.is_saved ## True 

मैं गारंटी नहीं दे सकते हैं कि यह कायम है डेटा भंडार। Google पर इसके बारे में कुछ भी नहीं मिला :)

एक तरफ नहीं, यह देखने के लिए कि क्या एक ndb.Model इंस्टेंस की कुंजी है, शायद यह संभवतः काम नहीं करेगी क्योंकि एक नया उदाहरण कभी भी भेजा जाने से पहले एक कुंजी प्राप्त करता है डेटास्टोर के लिए। जब आप ndb.Model क्लास का उदाहरण बनाते हैं तो क्या होता है यह देखने के लिए आप source code देख सकते हैं।

+1

यह कामकाज के रूप में उपयोग करने के लिए पर्याप्त है। तो मैं +1 वोट। यदि बेहतर समाधान दिखाई नहीं देगा तो मैं आपके जवाब को दो दिनों में स्वीकार करूंगा। – Sergey

+0

इस दृष्टिकोण के साथ एकमात्र नकारात्मक पक्ष जो वर्तमान में खड़ा है, यह है कि अगर किसी इकाई को बनाए जाने के बजाय पुनर्प्राप्त किया गया है तो 'is_saved'' गलत 'होगा। जो 'is_saved() 'के' db.Model' व्यवहार को मैप नहीं करता है। पूरा होने के लिए आप शायद '_post_get_hook' विधि जोड़ना चाहते हैं जो सत्य पर is_saved भी सेट करता है। –

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

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