Source

django-cache-utils / README.rst

Mikhail Korobov 0adb40c 





Mikhail Korobov 4b4a55f 


Mikhail Korobov 1312ac9 
Mikhail Korobov 4b4a55f 



Mikhail Korobov 1312ac9 
Mikhail Korobov 4b4a55f 
Mikhail Korobov 1312ac9 


Mikhail Korobov 4b4a55f 

Mikhail Korobov 0adb40c 

Mikhail Korobov 1312ac9 
Mikhail Korobov 0adb40c 







Mikhail Korobov 1312ac9 
Mikhail Korobov 0adb40c 






Mikhail Korobov 4b4a55f 

Mikhail Korobov 1312ac9 




























Mikhail Korobov 4b4a55f 
Mikhail Korobov 0adb40c 












































Mikhail Korobov 1312ac9 

Mikhail Korobov 0adb40c 



Mikhail Korobov 1312ac9 
Mikhail Korobov 0adb40c 


Mikhail Korobov 1312ac9 
Mikhail Korobov 0adb40c 


Mikhail Korobov 1312ac9 
Mikhail Korobov 0adb40c 

Mikhail Korobov 1312ac9 

Mikhail Korobov 0adb40c 



Mikhail Korobov 1312ac9 


==================
django-cache-utils
==================

django-cache-utils provides some utils for make cache-related work easier:

* ``cached`` decorator. It can be applied to function, method or classmethod
  and can be used with any django cache backend (built-in or third-party like
  django-newcache).

  Supports fine-grained invalidation for exact parameter set (with any backend)
  and bulk cache invalidation (only with ``group_backend``). Cache keys are
  human-readable because they are constructed from callable's full name and
  arguments and then sanitized to make memcached happy.

  Wrapped callable gets ``invalidate`` methods. Call ``invalidate`` with
  same arguments as function and the cached result for these arguments will be
  invalidated.

* ``group_backend``. It is a django memcached cache backend with group O(1)
  invalidation ability, dog-pile effect prevention using MintCache algorythm
  and project version support to allow gracefull updates and multiple django
  projects on same memcached instance.
  Long keys (>250) are auto-truncated and appended with md5 hash.

Installation
============

::

    pip install django-cache-utils

and then (optional)::

    # settings.py
    CACHE_BACKEND = 'cache_utils.group_backend://localhost:11211/'

Usage
=====

`cached` decorator can be used with any django caching backend (built-in or
third-party like django-newcache)::

    from cache_utils.decorators import cached

    @cached(60)
    def foo(x, y=0):
        print 'foo is called'
        return x+y

    foo(1,2) # foo is called
    foo(1,2)
    foo(5,6) # foo is called
    foo(5,6)
    foo.invalidate(1,2)
    foo(1,2) # foo is called
    foo(5,6)
    foo(x=2) # foo is called
    foo(x=2)

    class Foo(object):
        @cached(60)
        def foo(self, x,y):
            print "foo is called"
            return x+y

    obj = Foo()
    obj.foo(1,2) # foo is called
    obj.foo(1,2)


With ``group_backend`` `cached` decorator supports bulk O(1) invalidation::

    from django.db import models
    from cache_utils.decorators import cached

    class CityManager(models.Manager):

        # cache a method result. 'self' parameter is ignored
        @cached(60*60*24, 'cities')
        def default(self):
            return self.active()[0]

        # cache a method result. 'self' parameter is ignored, args and
        # kwargs are used to construct cache key
        @cached(60*60*24, 'cities')
        def get(self, *args, **kwargs):
            return super(CityManager, self).get(*args, **kwargs)


    class City(models.Model):
        # ... field declarations

        objects = CityManager()

        # an example how to cache django model methods by instance id
        def has_offers(self):
            @cached(30)
            def offer_count(pk):
                return self.offer_set.count()
            return history_count(self.pk) > 0

    # cache the function result based on passed parameter
    @cached(60*60*24, 'cities')
    def get_cities(slug)
        return City.objects.get(slug=slug)


    # cache for 'cities' group can be invalidated at once
    def invalidate_city(sender, **kwargs):
        cache.invalidate_group('cities')
    pre_delete.connect(invalidate_city, City)
    post_save.connect(invalidate_city, City)

Notes
=====

If decorated function returns None cache will be bypassed.

django-cache-utils use 2 reads from memcached to get a value if 'group'
argument is passed to 'cached' decorator::

    @cached(60)
    def foo(param)
        return ..

    @cached(60, 'my_group')
    def bar(param)
        return ..

    # 1 read from memcached
    value1 = foo(1)

    # 2 reads from memcached + ability to invalidate all values at once
    value2 = bar(1)


Running tests
=============

::

    cd test_project
    ./runtests.py
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.