2010-11-26 7 views
5

निम्नलिखित उदाहरण में, cached_attr का उपयोग मॉडल उदाहरण पर एक विशेषता प्राप्त करने या सेट करने के लिए किया जाता है जब डेटाबेस-महंगी संपत्ति (related_spam उदाहरण में) कहा जाता है। उदाहरण में, मैं प्रश्नों को सहेजने के लिए cached_spam का उपयोग करता हूं। जब मैं मूल्यों को प्राप्त करता हूं और मूल्य प्राप्त करते समय प्रिंट विवरण डालता हूं ताकि मैं इसका परीक्षण कर सकूं। मैं दृश्य में एक Egg उदाहरण पास करके और {{ egg.cached_spam }} का उपयोग कर देखने के लिए, साथ ही साथ Egg मॉडल कि खुद cached_spam को कॉल करने पर अन्य तरीकों में एक दृश्य में परीक्षण किया गया। जब मैंने Django के विकास सर्वर में खोल आउटपुट को समाप्त और परीक्षण किया, तो दिखाया गया कि विशेषता कैश कई बार याद किया गया था, साथ ही सफलतापूर्वक कई बार प्राप्त हुआ था। ऐसा असंगत प्रतीत होता है। उसी डेटा के साथ, जब मैंने छोटे बदलाव किए (जैसे प्रिंट स्टेटमेंट स्ट्रिंग को बदलना उतना ही छोटा) और रीफ्रेश किया गया (सभी समान डेटा के साथ), मिस/सफलताओं की अलग-अलग मात्रा में हुई। यह कैसे और क्यों हो रहा है? क्या यह कोड गलत या अत्यधिक समस्याग्रस्त है?पायथन - भविष्य की गणना से बचने के लिए एक संपत्ति को कैश करना

class Egg(models.Model): 
    ... fields 

    @property 
    def related_spam(self): 
     # Each time this property is called the database is queried (expected). 
     return Spam.objects.filter(egg=self).all() # Spam has foreign key to Egg. 

    @property 
    def cached_spam(self): 
     # This should call self.related_spam the first time, and then return 
     # cached results every time after that. 
     return self.cached_attr('related_spam') 

    def cached_attr(self, attr): 
     """This method (normally attached via an abstract base class, but put 
     directly on the model for this example) attempts to return a cached 
     version of a requested attribute, and calls the actual attribute when 
     the cached version isn't available.""" 
     try: 
      value = getattr(self, '_p_cache_{0}'.format(attr)) 
      print('GETTING - {0}'.format(value)) 
     except AttributeError: 
      value = getattr(self, attr) 
      print('SETTING - {0}'.format(value)) 
      setattr(self, '_p_cache_{0}'.format(attr), value) 
     return value 
+1

मैं इस झुंझलाहट के खिलाफ आया था और महसूस किया कि इस समस्या को हल करने के लिए एक और तरीका परिकलित परिणाम के लिए एक अन्य नाम बनाना 'with' टेम्पलेट टैग का उपयोग करने के लिए है। – nedned

+0

@ हम्बल - thx, यह वास्तव में एक बहुत उपयोगी नोट है। – orokusaki

उत्तर

9

आपके कोड के साथ कुछ भी गलत नहीं है, जहां तक ​​यह जाता है। समस्या शायद वहां नहीं है, लेकिन आप उस कोड का उपयोग कैसे करते हैं।

मुख्य बात यह जानना है कि मॉडल के उदाहरणों में पहचान नहीं है। इसका मतलब यह है कि यदि आप कहीं अंडे ऑब्जेक्ट को तुरंत चालू करते हैं, और कहीं और अलग होते हैं, भले ही वे समान अंतर्निहित डेटाबेस पंक्ति का संदर्भ लें, वे आंतरिक स्थिति साझा नहीं करेंगे। इसलिए cached_attr पर कॉल करने से कैश को दूसरे में पॉप्युलेट नहीं किया जाएगा।

उदाहरण के लिए

, यह मानते हुए आप अंडे के लिए एक ForeignKey के साथ एक RelatedObject वर्ग है:

my_first_egg = Egg.objects.get(pk=1) 
my_related_object = RelatedObject.objects.get(egg__pk=1) 
my_second_egg = my_related_object.egg 

यहाँ my_first_egg और my_second_egg दोनों पी 1 के साथ डेटाबेस पंक्ति का उल्लेख है, लेकिन वे नहीं एक ही वस्तु हैं:

>>> my_first_egg.pk == my_second_egg.pk 
True 
>>> my_first_egg is my_second_egg 
False 

तो, my_first_egg पर कैश भरने my_second_egg पर इसे भरने नहीं करता है।

और, ज़ाहिर है, वस्तुओं अनुरोध भर में बना रहेगा नहीं (जब तक कि वे विशेष रूप से वैश्विक बना रहे हैं, जो भयानक है), इसलिए कैश या तो जारी रहती है नहीं होंगे।

+0

धन्यवाद। प्रदान किया गया उदाहरण है, मुझे लगता है, वास्तव में क्या हो रहा है। मुझे लगता है कि मेरे कोड में मुझे इतने सारे उदाहरण मिल रहे हैं। एक ऑब्जेक्ट जिसमें कोड की मेरी समीक्षा के आधार पर केवल 2 अलग-अलग उदाहरण हो सकते हैं ('my_related_object.egg' में से एक) में 4 उदाहरण हैं। मुझे लगता है कि यह मेरे मॉडल के पूर्ण ओवरहाल के लिए समय है; सभी 200 लाइन 8 ( – orokusaki

+0

मुझे अपराधी मिला! मेरे पास एक दुष्ट विधि थी जो एक ही ऑब्जेक्ट को फिर से प्राप्त कर रही थी (मेरे संपादक की खोज को अभी नहीं मिला क्योंकि फ़िल्टरिंग के कारण सिंटैक्स थोड़ा अलग था)। इसके साथ, संयुक्त मेरे कैशिंग (सरल यादगार) विधि और एक चालाक चयन से संबंधित मुझे 31 प्रश्नों को 3 तक नीचे मिला !!! सूचक के लिए धन्यवाद। – orokusaki

1

एचटीपी सर्वर जो स्केल साझा किए जाते हैं-कुछ भी नहीं; आप सिंगलटन होने पर कुछ भी भरोसा नहीं कर सकते हैं। राज्य साझा करने के लिए, आपको एक विशेष उद्देश्य सेवा से कनेक्ट करने की आवश्यकता है।

Django के caching support आपके उपयोग के मामले के लिए उपयुक्त है। यह जरूरी नहीं है कि एक वैश्विक सिंगलटन भी हो; यदि आप locmem:// का उपयोग करते हैं, तो यह प्रक्रिया-स्थानीय होगा, जो अधिक कुशल विकल्प हो सकता है।

+0

यह केवल प्रति-अनुरोध कैशिंग के लिए है। मैं अपने कैशिंग फ्रेमवर्क को लागू करने की कोशिश कभी नहीं करूंगा। मैं उसी अनुरोध के दौरान डेटाबेस से ऑब्जेक्ट खींचने के लिए बस बीमार हूं। – orokusaki

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