2010-04-22 7 views
10

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

अगर मैं संकेत सार मॉडल को निर्दिष्ट कनेक्ट करते हैं, इस व्युत्पन्न मॉडल के लिए प्रचार नहीं करता है:

pre_delete.connect(clear_cache, sender=MyAbstractModel, weak=False) 

अगर मैं एक init, में संकेत कनेक्ट करने के लिए है, जहां मैं व्युत्पन्न वर्ग प्राप्त कर सकते हैं की कोशिश नाम, यह काम करता है, लेकिन मुझे डर है कि यह कैश को कई बार साफ़ करने का प्रयास करेगा क्योंकि मैंने एक व्युत्पन्न मॉडल शुरू किया है, न केवल एक बार।

मुझे सिग्नल को कहां से जोड़ना चाहिए?

उत्तर

4

अपने मॉडल के लिए एक कस्टम प्रबंधक बनाएं। contribute_to_class विधि में, यह class_prepared के लिए एक संकेत सेट करें। यह सिग्नल एक फ़ंक्शन को कॉल करता है जो मॉडल को अधिक संकेत देता है।

+1

मुझे इसके पीछे विचार मिलता है, लेकिन क्या आप संभवतः एक उदाहरण के साथ विस्तार कर सकते हैं? यह वास्तव में मेरी वर्तमान परियोजना में चीजों को डीआरवाई रखने में मदद करेगा। –

+0

संपादित करें: मैंने आपके सुझाव पर अपने सुझाव पर काम करने की कोशिश की .. यह मेरे लिए काम करता है, लेकिन मैं 100% निश्चित नहीं हूं! –

+0

'contribute_to_class' के लिए कोई आधिकारिक दस्तावेज़ नहीं है ... – Raffi

2

मुझे लगता है कि आप प्रेषक निर्दिष्ट किए बिना post_delete से कनेक्ट कर सकते हैं, और फिर जांचें कि वास्तविक प्रेषक मॉडल कक्षाओं की सूची में है या नहीं। कुछ ऐसा:

def my_handler(sender, **kwargs): 
    if sender.__class__ in get_models(someapp.models): 
     ... 

जाहिर है आपको अधिक परिष्कृत जांच आदि की आवश्यकता होगी, लेकिन आपको विचार मिल जाएगा।

3

जस्टिन लिली के उत्तर पर बिल्डिंग, मैंने एक कस्टम मैनेजर बनाया है जो कक्षा के प्रत्येक बच्चे को पोस्ट_सेव सिग्नल बांधता है, चाहे वह सार हो या नहीं।

यह एक-एक, खराब परीक्षण कोड है, इसलिए सावधान रहें! हालांकि, यह अब तक काम करता है।

इस उदाहरण में, हम एक अमूर्त मॉडल को कैशडोडेलमेनर को प्रबंधक के रूप में परिभाषित करने की अनुमति देते हैं, जो मॉडल और उसके बच्चों को मूल कैशिंग कार्यक्षमता बढ़ाता है। यह आपको अस्थिर कुंजी की एक सूची को परिभाषित करने की अनुमति देता है जिसे प्रत्येक सहेजने पर हटाया जाना चाहिए (इसलिए post_save सिग्नल) और कैश कुंजी उत्पन्न करने के साथ-साथ पुनर्प्राप्ति, सेटिंग और हटाने की कुंजी बनाने के लिए कुछ सहायक कार्यों को जोड़ता है।

यह निश्चित रूप से मानता है कि आपके पास कैश बैकएंड सेटअप है और ठीक से काम कर रहा है।

# helperapp\models.py 
# -*- coding: UTF-8 
from django.db import models 
from django.core.cache import cache 

class CachedModelManager(models.Manager): 
    def contribute_to_class(self, model, name): 
     super(CachedModelManager, self).contribute_to_class(model, name) 

     setattr(model, 'volatile_cache_keys', 
       getattr(model, 'volatile_cache_keys', [])) 

     setattr(model, 'cache_key', getattr(model, 'cache_key', cache_key)) 
     setattr(model, 'get_cache', getattr(model, 'get_cache', get_cache)) 
     setattr(model, 'set_cache', getattr(model, 'set_cache', set_cache)) 
     setattr(model, 'del_cache', getattr(model, 'del_cache', del_cache)) 

     self._bind_flush_signal(model) 

    def _bind_flush_signal(self, model): 
     models.signals.post_save.connect(flush_volatile_keys, model) 

def flush_volatile_keys(sender, **kwargs): 
    instance = kwargs.pop('instance', False) 

    for key in instance.volatile_cache_keys: 
     instance.del_cache(key) 

def cache_key(instance, key): 
    if not instance.pk: 
     name = "%s.%s" % (instance._meta.app_label, instance._meta.module_name) 
     raise models.ObjectDoesNotExist("Can't generate a cache key for " + 
             "this instance of '%s' " % name + 
             "before defining a primary key.") 
    else: 
     return "%s.%s.%s.%s" % (instance._meta.app_label, 
           instance._meta.module_name, 
           instance.pk, key) 

def get_cache(instance, key): 
    result = cache.get(instance.cache_key(key)) 
    return result 

def set_cache(instance, key, value, timeout=60*60*24*3): 
    result = cache.set(instance.cache_key(key), value, timeout) 
    return result 

def del_cache(instance, key): 
    result = cache.delete(instance.cache_key(key)) 
    return result 


# myapp\models.py 
from django.contrib.auth.models import User 
from django.db import models 

from helperapp.models import CachedModelManager 

class Abstract(models.Model): 
    creator = models.ForeignKey(User) 

    cache = CachedModelManager() 

    class Meta: 
     abstract = True 


class Community(Abstract): 
    members = models.ManyToManyField(User) 

    volatile_cache_keys = ['members_list',] 

    @property 
    def members_list(self): 
     result = self.get_cache('members_list') 

     if not result: 
      result = self.members.all() 
      self.set_cache('members_list', result) 

     return result 

पैच का स्वागत है!

+0

इसे एक स्निपेट में बदल दिया: http://djangosnippets.org/snippets/2749/ –

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