Django

Code

Ticket #7338: method_cache_with_invalidation_r9787.diff

File method_cache_with_invalidation_r9787.diff, 5.2 kB (added by msaelices, 1 year ago)

Caching with manager invalidation

  • django/db/models/sql/query.py

    old new  
    1919from django.db.models.query_utils import select_related_descend 
    2020from django.db.models.sql import aggregates as base_aggregates_module 
    2121from django.db.models.sql.where import WhereNode, Constraint, EverythingNode, AND, OR 
     22from django.core.cache import cache 
    2223from django.core.exceptions import FieldError 
    2324from datastructures import EmptyResultSet, Empty, MultiJoin 
    2425from constants import * 
     
    9091        self.extra_params = () 
    9192        self.extra_order_by = () 
    9293 
     94        # Cached queryset atribute. None means no cached 
     95        self.cache_timeout = None 
     96        self.cache_key = None 
     97 
    9398    def __str__(self): 
    9499        """ 
    95100        Returns the query as a string of SQL with the parameter values 
     
    190195        obj.extra_where = self.extra_where 
    191196        obj.extra_params = self.extra_params 
    192197        obj.extra_order_by = self.extra_order_by 
     198        obj.cache_timeout = self.cache_timeout 
     199        obj.cache_key = self.cache_key 
    193200        if self.filter_is_sticky and self.used_aliases: 
    194201            obj.used_aliases = self.used_aliases.copy() 
    195202        else: 
     
    237244        """ 
    238245        resolve_columns = hasattr(self, 'resolve_columns') 
    239246        fields = None 
    240         for rows in self.execute_sql(MULTI): 
     247        if self.cache_timeout is not None: 
     248            # Check cache for stored objects from an exactly equal query 
     249            k = str(self) 
     250            try: 
     251                import hashlib 
     252            except ImportError: 
     253                import sha 
     254                k = sha.new(k).hexdigest() 
     255            else: 
     256                k = hashlib.sha1(k).hexdigest() 
     257 
     258            self.cache_key = k 
     259 
     260            if cache.has_key(k) and cache.get(k): 
     261                sql_result = cache.get(k, []) 
     262            else: 
     263                cache.set(k, [i for i in self.execute_sql(MULTI)], self.cache_timeout) 
     264                sql_result = cache.get(k, []) 
     265                # register this cache key for allowing later invalidation 
     266                model_cache_key = self.model._meta.cache_key 
     267                cache_register = cache.get(model_cache_key, []) 
     268                cache_register.append(k) 
     269                cache.set(model_cache_key, cache_register) 
     270        else: 
     271            sql_result = self.execute_sql(MULTI) 
     272 
     273        for rows in sql_result: 
    241274            for row in rows: 
    242275                if resolve_columns: 
    243276                    if fields is None: 
  • django/db/models/manager.py

    old new  
    33from django.db.models.query import QuerySet, EmptyQuerySet, insert_query 
    44from django.db.models import signals 
    55from django.db.models.fields import FieldDoesNotExist 
     6from django.core.cache import cache 
    67 
    78def ensure_default_manager(sender, **kwargs): 
    89    cls = sender 
     
    140141    def reverse(self, *args, **kwargs): 
    141142        return self.get_query_set().reverse(*args, **kwargs) 
    142143 
     144    def cache(self, timeout=20): 
     145        return self.get_query_set().cache(timeout=timeout) 
     146 
     147    def flush_cache(self): 
     148        model_cache_key = self.model._meta.cache_key 
     149        cache_register = cache.get(model_cache_key, []) 
     150        for cached_queryset_key in cache_register: 
     151            cache.delete(cached_queryset_key) 
     152        cache.delete(model_cache_key) 
     153 
    143154    def _insert(self, values, **kwargs): 
    144155        return insert_query(self.model, values, **kwargs) 
    145156 
  • django/db/models/options.py

    old new  
    4444        self.abstract = False 
    4545        self.parents = SortedDict() 
    4646        self.duplicate_targets = {} 
     47        self.cache_key = None 
    4748        # Managers that have been inherited from abstract base classes. These 
    4849        # are passed onto any children. 
    4950        self.abstract_managers = [] 
     
    5859        self.object_name = cls.__name__ 
    5960        self.module_name = self.object_name.lower() 
    6061        self.verbose_name = get_verbose_name(self.object_name) 
     62        self.cache_key = 'modelcache-%s.%s' % (self.app_label, self.module_name) 
    6163 
    6264        # Next, apply any overridden values from 'class Meta'. 
    6365        if self.meta: 
  • django/db/models/query.py

    old new  
    640640        clone.query.standard_ordering = not clone.query.standard_ordering 
    641641        return clone 
    642642 
     643    def cache(self, timeout=20): 
     644        """ 
     645        Forces the current queryset to check if a exact equal query has been 
     646        stored in the cache. The expiration time is the seconds in 'timeout' 
     647        variable. 
     648        """ 
     649        clone = self._clone() 
     650        clone.query.cache_timeout = timeout 
     651        return clone 
     652 
    643653    ################### 
    644654    # PRIVATE METHODS # 
    645655    ###################