Giter VIP home page Giter VIP logo

django-fancy-cache's Introduction

django-fancy-cache

Copyright Peter Bengtsson, [email protected], 2013-2022

License: BSD

About django-fancy-cache

A Django cache_page decorator on steroids.

Unlike the stock django.views.decorators.cache.change_page this decorator makes it possible to set a key_prefix that is a callable. This callable is passed the request and if it returns None the page is not cached.

Also, you can set another callable called post_process_response (which is passed the response and the request) which can do some additional changes to the response before it's set in cache.

Lastly, you can set post_process_response_always=True so that the post_process_response callable is always called, even when the response is coming from the cache.

How to use it

In your Django views:

from fancy_cache import cache_page
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

@cache_page(60 * 60)
def myview(request):
    return render(request, 'page1.html')

def prefixer(request):
    if request.method != 'GET':
        return None
    if request.GET.get('no-cache'):
        return None
    return 'myprefix'

@cache_page(60 * 60, key_prefix=prefixer)
def myotherview(request):
    return render(request, 'page2.html')

def post_processor(response, request):
    response.content += '<!-- this was post processed -->'
    return response

@cache_page(
    60 * 60,
    key_prefix=prefixer,
    post_process_response=post_processor)
def yetanotherotherview(request):
    return render(request, 'page3.html')


class MyClassBasedView(TemplateView):
    template_name = 'page4.html'

    @method_decorator(cache_page(60*60))
    def get(self, request, *args, **kwargs):
        return super().get(request, *args, **kwargs)

Optional uses

If you want to you can have django-fancy-cache record every URL it caches. This can be useful for things like invalidation or curious statistical inspection.

You can either switch this on on the decorator itself. Like this:

from fancy_cache import cache_page

@cache_page(60 * 60, remember_all_urls=True)
def myview(request):
    return render(request, 'page1.html')

Or, more conveniently to apply it to all uses of the cache_page decorator you can set the default in your settings with:

FANCY_REMEMBER_ALL_URLS = True

Now, suppose you have the this option enabled. Now you can do things like this:

>>> from fancy_cache.memory import find_urls
>>> list(find_urls(['/some/searchpath', '/or/like/*/this.*']))
>>> # or, to get all:
>>> list(find_urls([]))

There is also another option to this and that is to purge (aka. invalidate) the remembered URLs. You simply all the purge=True option like this:

>>> from fancy_cache.memory import find_urls
>>> list(find_urls([], purge=True))

Note: Since find_urls() returns a generator, the purging won't happen unless you exhaust the generator. E.g. looping over it or turning it into a list.

If you are using Memcached, you must enable check-and-set to remember all urls by enabling the FANCY_USE_MEMCACHED_CHECK_AND_SET flag and enabling cas in your CACHES settings:

# in settings.py

FANCY_USE_MEMCACHED_CHECK_AND_SET = True

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': '127.0.0.1:11211',
        # This OPTIONS setting enables Memcached check-and-set which is
        # required for remember_all_urls or FANCY_REMEMBER_ALL_URLS.
        'OPTIONS': {
            'behaviors': {
                'cas': True
            }
        }
    }
 }

The second way to inspect all recorded URLs is to use the fancy-cache management command. This is only available if you have added fancy_cache to your INSTALLED_APPS setting. Now you can do this:

$ ./manage.py fancy-cache --help
$ ./manage.py fancy-cache
$ ./manage.py fancy-cache /some/searchpath /or/like/*/this.*
$ ./manage.py fancy-cache /some/place/* --purge
$ # or to purge them all!
$ ./manage.py fancy-cache --purge

Note, it will only print out URLs that if found (and purged, if applicable).

The third way to inspect the recorded URLs is to add this to your root urls.py:

url(r'fancy-cache', include('fancy_cache.urls')),

Now, if you visit http://localhost:8000/fancy-cache you get a table listing every URL that django-fancy-cache has recorded.

Optional uses (for the exceptionally curious)

If you have enabled FANCY_REMEMBER_ALL_URLS you can also enable FANCY_REMEMBER_STATS_ALL_URLS in your settings. What this does is that it attempts to count the number of cache hits and cache misses you have for each URL.

This counting of hits and misses is configured to last "a long time". Possibly longer than you cache your view. So, over time you can expect to have more than one miss because your view cache expires and it starts over.

You can see the stats whenever you use any of the ways described in the section above. For example like this:

>>> from fancy_cache.memory import find_urls
>>> found = list(find_urls([]))[0]
>>> found[0]
'/some/page.html'
>>> found[2]
{'hits': 1235, 'misses': 12}

There is obviously a small additional performance cost of using the FANCY_REMEMBER_ALL_URLS and/or FANCY_REMEMBER_STATS_ALL_URLS in your project so only use it if you don't have any smarter way to invalidate, for debugging or if you really want make it possible to purge all cached responses when you run an upgrade of your site or something.

Running the test suite

The simplest way is to simply run:

$ pip install tox
$ tox

Or to run it without tox you can simply run:

$ export PYTHONPATH=`pwd`
$ export DJANGO_SETTINGS_MODULE=fancy_tests.tests.settings
$ django-admin.py test

Changelog

1.2.1
  • Bugfix: conflict between the DummyCache backend when FANCY_USE_MEMCACHED_CHECK_AND_SET is True
1.2.0
  • Restructure the remembered_urls cache dict to clean up stale entries
  • Update FancyCacheMiddleware to match latest Django CacheMiddlware (Also renames to FancyCacheMiddleware)
  • Apply Memcached check-and-set to the delete_keys function if settings.FANCY_USE_MEMCACHED_CHECK_AND_SET = True
  • Drop support for Python <3.6
  • Add support for Python 3.10 and Django 4.0
1.1.0
  • If you use Memcached you can set settings.FANCY_USE_MEMCACHED_CHECK_AND_SET = True so that you can use cache._cache.cas which only workd with Memcached
1.0.0
  • Drop support for Python <3.5 and Django <2.2.0
0.11.0
  • Fix for parse_qs correctly between Python 2 and Python 3
0.10.0
  • Fix for keeping blank strings in query strings. #39
0.9.0
  • Django 1.10 support
0.8.2
  • Remove deprecated way to define URL patterns and tests in python 3.5
0.8.1
  • Ability to specify different cache backends to be used peterbe#31
0.8.0
  • Started keeping a Changelog

django-fancy-cache's People

Contributors

aaronvanderlip avatar idealatom avatar justinfay avatar peterbe avatar pigmonkey avatar pyman avatar regadas avatar skorokithakis avatar timbutler avatar ypcrumble avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.