Ticket #7338: method_cache_with_invalidation_r9787.diff

File method_cache_with_invalidation_r9787.diff, 5.2 KB (added by msaelices, 7 years ago)

Caching with manager invalidation

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

     
    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

     
    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

     
    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

     
    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    ###################
Back to Top