Skip to content

Commit

Permalink
Adds CACHALOT_ONLY_CACHABLE_TABLES.
Browse files Browse the repository at this point in the history
  • Loading branch information
BertrandBordage committed Oct 5, 2015
1 parent 5b0ffb9 commit a8b77c6
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 2 deletions.
1 change: 1 addition & 0 deletions cachalot/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Settings(object):
CACHALOT_CACHE = 'default'
CACHALOT_CACHE_RANDOM = False
CACHALOT_INVALIDATE_RAW = True
CACHALOT_ONLY_CACHABLE_TABLES = frozenset()
CACHALOT_UNCACHABLE_TABLES = frozenset(('django_migrations',))
CACHALOT_QUERY_KEYGEN = 'cachalot.utils.get_query_cache_key'
CACHALOT_TABLE_KEYGEN = 'cachalot.utils.get_table_cache_key'
Expand Down
67 changes: 66 additions & 1 deletion cachalot/tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
from unittest import skipIf

from django.conf import settings
from django.contrib.auth.models import User
from django.core.cache import DEFAULT_CACHE_ALIAS
from django.db import connection
from django.test import TransactionTestCase
from django.test.utils import override_settings

from .models import Test
from .models import Test, TestParent, TestChild


class SettingsTestCase(TransactionTestCase):
Expand Down Expand Up @@ -104,6 +105,50 @@ def test_invalidate_raw(self):
with self.assertNumQueries(0):
list(Test.objects.all())

def test_only_cachable_tables(self):
with self.settings(CACHALOT_ONLY_CACHABLE_TABLES=('cachalot_test',)):
with self.assertNumQueries(1):
list(Test.objects.all())
with self.assertNumQueries(0):
list(Test.objects.all())

with self.assertNumQueries(1):
list(TestParent.objects.all())
with self.assertNumQueries(1):
list(TestParent.objects.all())

with self.assertNumQueries(1):
list(Test.objects.select_related('owner'))
with self.assertNumQueries(1):
list(Test.objects.select_related('owner'))

with self.assertNumQueries(1):
list(TestParent.objects.all())
with self.assertNumQueries(0):
list(TestParent.objects.all())

with self.settings(CACHALOT_ONLY_CACHABLE_TABLES=(
'cachalot_test', 'cachalot_testchild', 'auth_user')):
with self.assertNumQueries(1):
list(Test.objects.select_related('owner'))
with self.assertNumQueries(0):
list(Test.objects.select_related('owner'))

# TestChild uses multi-table inheritance, and since its parent,
# 'cachalot_testparent', is not cachable, a basic
# TestChild query can’t be cached
with self.assertNumQueries(1):
list(TestChild.objects.all())
with self.assertNumQueries(1):
list(TestChild.objects.all())

# However, if we only fetch data from the 'cachalot_testchild'
# table, it’s cachable.
with self.assertNumQueries(1):
list(TestChild.objects.only('public'))
with self.assertNumQueries(0):
list(TestChild.objects.only('public'))

def test_uncachable_tables(self):
with self.settings(CACHALOT_UNCACHABLE_TABLES=('cachalot_test',)):
with self.assertNumQueries(1):
Expand All @@ -121,3 +166,23 @@ def test_uncachable_tables(self):
list(Test.objects.all())
with self.assertNumQueries(1):
list(Test.objects.all())

def test_only_cachable_and_uncachable_table(self):
with self.settings(
CACHALOT_ONLY_CACHABLE_TABLES=('cachalot_test',
'cachalot_testparent'),
CACHALOT_UNCACHABLE_TABLES=('cachalot_test',)):
with self.assertNumQueries(1):
list(Test.objects.all())
with self.assertNumQueries(1):
list(Test.objects.all())

with self.assertNumQueries(1):
list(TestParent.objects.all())
with self.assertNumQueries(0):
list(TestParent.objects.all())

with self.assertNumQueries(1):
list(User.objects.all())
with self.assertNumQueries(1):
list(User.objects.all())
5 changes: 4 additions & 1 deletion cachalot/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ def _get_tables(query, db_alias):
additional_tables = _get_tables_from_sql(connections[db_alias], sql)
tables.update(additional_tables)

if not tables.isdisjoint(cachalot_settings.CACHALOT_UNCACHABLE_TABLES):
whitelist = cachalot_settings.CACHALOT_ONLY_CACHABLE_TABLES
blacklist = cachalot_settings.CACHALOT_UNCACHABLE_TABLES
if (whitelist and not tables.issubset(whitelist)) \
or not tables.isdisjoint(blacklist):
raise UncachableQuery
return tables

Expand Down
11 changes: 11 additions & 0 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ Settings
:Description: If set to ``False``, disables automatic invalidation on raw
SQL queries – read :ref:`Raw queries limits` for more info


``CACHALOT_ONLY_CACHABLE_TABLES``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:Default: ``frozenset()``
:Description:
Sequence of SQL table names that will be the only ones django-cachalot
will cache. Only queries with a subset of these tables will be cached.
Use a frozenset over other sequence types for a tiny performance boost.


.. _CACHALOT_UNCACHABLE_TABLES:

``CACHALOT_UNCACHABLE_TABLES``
Expand Down

0 comments on commit a8b77c6

Please sign in to comment.