# coding: utf-8 from __future__ import unicode_literals 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, TestParent, TestChild class SettingsTestCase(TransactionTestCase): def setUp(self): if connection.vendor == 'mysql': # We need to reopen the connection or Django # will execute an extra SQL request below. connection.cursor() @override_settings(CACHALOT_ENABLED=False) def test_decorator(self): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(1): list(Test.objects.all()) def test_django_override(self): with self.settings(CACHALOT_ENABLED=False): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(1): list(Test.objects.all()) with self.settings(CACHALOT_ENABLED=True): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(0): list(Test.objects.all()) def test_enabled(self): with self.settings(CACHALOT_ENABLED=True): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(0): list(Test.objects.all()) with self.settings(CACHALOT_ENABLED=False): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(0): list(Test.objects.all()) is_sqlite = connection.vendor == 'sqlite' with self.settings(CACHALOT_ENABLED=False): with self.assertNumQueries(2 if is_sqlite else 1): t = Test.objects.create(name='test') with self.assertNumQueries(1): data = list(Test.objects.all()) self.assertListEqual(data, [t]) @skipIf(len(settings.CACHES) == 1, 'We can’t change the cache used since there’s only one configured') def test_cache(self): with self.settings(CACHALOT_CACHE=DEFAULT_CACHE_ALIAS): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(0): list(Test.objects.all()) other_cache_alias = next(alias for alias in settings.CACHES if alias != DEFAULT_CACHE_ALIAS) with self.settings(CACHALOT_CACHE=other_cache_alias): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(0): list(Test.objects.all()) def test_cache_random(self): with self.assertNumQueries(1): list(Test.objects.order_by('?')) with self.assertNumQueries(1): list(Test.objects.order_by('?')) with self.settings(CACHALOT_CACHE_RANDOM=True): with self.assertNumQueries(1): list(Test.objects.order_by('?')) with self.assertNumQueries(0): list(Test.objects.order_by('?')) def test_invalidate_raw(self): with self.assertNumQueries(1): list(Test.objects.all()) with self.settings(CACHALOT_INVALIDATE_RAW=False): with self.assertNumQueries(1): with connection.cursor() as cursor: cursor.execute("UPDATE %s SET name = 'new name';" % Test._meta.db_table) 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.values('public')) with self.assertNumQueries(0): list(TestChild.objects.values('public')) def test_uncachable_tables(self): with self.settings(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(Test.objects.all()) with self.assertNumQueries(0): list(Test.objects.all()) with self.settings(CACHALOT_UNCACHABLE_TABLES=('cachalot_test',)): with self.assertNumQueries(1): 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())