Quick start¶
Requirements¶
- Django 1.6 or 1.7
- Python 2.6, 2.7, 3.2, 3.3, or 3.4
- a cache configured as
'default'with one of these backends:- django-redis
- memcached (using either python-memcached or pylibmc (but pylibmc is only supported with Django >= 1.7))
- filebased (only with Django >= 1.7 as it was not thread-safe before)
- locmem (but it’s not shared between processes, see Limits)
- one of these databases:
- PostgreSQL
- SQLite
- MySQL (but you probably don’t need django-cachalot in this case, see Limits)
Usage¶
pip install django-cachalot- Add
'cachalot',to yourINSTALLED_APPS - Be aware of the few limits
- If you use
django-debug-toolbar,
you can add
'cachalot.panels.CachalotPanel',to yourDEBUG_TOOLBAR_PANELS - If you need to invalidate all django-cachalot cache keys from an external script
– typically after restoring a SQL database –, simply run
./manage.py invalidate_cachalot - Enjoy!
Settings¶
CACHALOT_ENABLED¶
| Default: | True |
|---|---|
| Description: | If set to False, disables SQL caching but keeps invalidating
to avoid stale cache |
CACHALOT_CACHE¶
| Default: | 'default' |
|---|---|
| Description: | Alias of the cache from CACHES used by django-cachalot |
CACHALOT_CACHE_RANDOM¶
| Default: | False |
|---|---|
| Description: | If set to True, caches random queries
(those with order_by('?')) |
CACHALOT_INVALIDATE_RAW¶
| Default: | True |
|---|---|
| Description: | If set to False, disables automatic invalidation on raw
SQL queries – read Raw SQL queries for more info |
CACHALOT_UNCACHABLE_TABLES¶
| Default: | frozenset(('django_migrations',)) |
|---|---|
| Description: | Sequence of SQL table names that will be ignored by django-cachalot.
Queries using a table mentioned in this setting will not be cached.
Always keep 'django_migrations' in it, otherwise you may face
some issues, especially during tests.
Use a frozenset over other sequence types for a tiny performance boost. |
CACHALOT_QUERY_KEYGEN¶
| Default: | 'cachalot.utils.get_query_cache_key' |
|---|---|
| Description: | Python module path to the function that will be used to generate the cache key of a SQL query |
CACHALOT_TABLE_KEYGEN¶
| Default: | 'cachalot.utils.get_table_cache_key' |
|---|---|
| Description: | Python module path to the function that will be used to generate the cache key of a SQL table |
Dynamic overriding¶
Django-cachalot is built so that its settings can be dynamically changed. For example:
from django.conf import settings
from django.test.utils import override_settings
with override_settings(CACHALOT_ENABLED=False):
# SQL queries are not cached in this block
@override_settings(CACHALOT_CACHE='another_alias')
def your_function():
# What’s in this function uses another cache
# Globally disables SQL caching until you set it back to True
settings.CACHALOT_ENABLED = False
Signal¶
cachalot.signals.post_invalidation is available if you need to do something
just after a cache invalidation (when you modify something in a SQL table).
sender is the name of the SQL table invalidated, and a keyword argument
db_alias explains which database is affected by the invalidation.
Be careful when you specify sender, as it is sensible to string type.
To be sure, use Model._meta.db_table.
Example:
from cachalot.signals import post_invalidation
from django.dispatch import receiver
from django.core.mail import mail_admins
from django.contrib.auth import *
# This prints a message to the console after each table invalidation
def invalidation_debug(sender, **kwargs):
db_alias = kwargs['db_alias']
print('%s was invalidated in the DB configured as %s'
% (sender, db_alias))
post_invalidation.connect(invalidation_debug)
# Using the `receiver` decorator is just a nicer way
# to write the same thing as `signal.connect`.
# Here we specify `sender` so that the function is executed only if
# the table invalidated is the one specified.
# We also connect it several times to be executed for several senders.
@receiver(post_invalidation, sender=User.groups.through._meta.db_table)
@receiver(post_invalidation, sender=User.user_permissions.through._meta.db_table)
@receiver(post_invalidation, sender=Group.permissions.through._meta.db_table)
def warn_admin(sender, **kwargs):
mail_admins('User permissions changed',
'Someone probably gained or lost Django permissions.')