diff --git a/cachalot/tests/migrations/0001_initial.py b/cachalot/tests/migrations/0001_initial.py index abe8511..7438a62 100644 --- a/cachalot/tests/migrations/0001_initial.py +++ b/cachalot/tests/migrations/0001_initial.py @@ -23,6 +23,7 @@ class Migration(migrations.Migration): ('datetime', models.DateTimeField(null=True, blank=True)), ('owner', models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True)), ('permission', models.ForeignKey(blank=True, to='auth.Permission', null=True)), + ('bin', models.BinaryField(null=True, blank=True)), ], options={ 'ordering': ('name',), diff --git a/cachalot/tests/migrations/0002_auto_20150416_0933.py b/cachalot/tests/migrations/0002_auto_20150416_0933.py deleted file mode 100644 index a28fd09..0000000 --- a/cachalot/tests/migrations/0002_auto_20150416_0933.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('cachalot', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='TestOne', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=20)), - ], - ), - migrations.CreateModel( - name='TestThese', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=20)), - ], - ), - migrations.AddField( - model_name='testone', - name='have_lots_of_these', - field=models.ManyToManyField(to='cachalot.TestThese', null=True, blank=True), - ), - ] diff --git a/cachalot/tests/models.py b/cachalot/tests/models.py index 642df57..c403900 100644 --- a/cachalot/tests/models.py +++ b/cachalot/tests/models.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals from django.conf import settings from django.db.models import ( Model, CharField, ForeignKey, BooleanField, DateField, DateTimeField, - ManyToManyField) + ManyToManyField, BinaryField) class Test(Model): @@ -15,6 +15,7 @@ class Test(Model): date = DateField(null=True, blank=True) datetime = DateTimeField(null=True, blank=True) permission = ForeignKey('auth.Permission', null=True, blank=True) + bin = BinaryField(null=True, blank=True) class Meta(object): app_label = 'cachalot' diff --git a/cachalot/tests/read.py b/cachalot/tests/read.py index 8f1027a..b5a99a0 100644 --- a/cachalot/tests/read.py +++ b/cachalot/tests/read.py @@ -119,6 +119,24 @@ class ReadTestCase(TransactionTestCase): self.assertListEqual(data2, data1) self.assertListEqual(data2, [self.t2]) + with self.assertNumQueries(1): + data1 = list(Test.objects.filter( + date__gt=datetime.date(1900, 1, 1))) + with self.assertNumQueries(0): + data2 = list(Test.objects.filter( + date__gt=datetime.date(1900, 1, 1))) + self.assertListEqual(data2, data1) + self.assertListEqual(data2, [self.t2]) + + with self.assertNumQueries(1): + data1 = list(Test.objects.filter( + datetime__lt=datetime.datetime(1900, 1, 1))) + with self.assertNumQueries(0): + data2 = list(Test.objects.filter( + datetime__lt=datetime.datetime(1900, 1, 1))) + self.assertListEqual(data2, data1) + self.assertListEqual(data2, [self.t1]) + def test_filter_empty(self): with self.assertNumQueries(1): data1 = list(Test.objects.filter(public=True, @@ -618,3 +636,29 @@ class ReadTestCase(TransactionTestCase): with self.assertNumQueries(0): list(Test.objects.extra(tables=['Clémentine'])) cursor.execute('DROP TABLE %s;' % table_name) + + def test_binary_field(self): + """ + Tests if queries on binary data are not cached. + Since binary fields use different classes with no clear way to hash + their values, it’s wiser not to cache them. + + The only exception is MySQL, which serializes binary to a simple + Python bytes (str in Python 2). + """ + is_mysql = connection.vendor == 'mysql' + + with self.assertNumQueries(1): + list(Test.objects.filter(bin=None)) + with self.assertNumQueries(0): + list(Test.objects.filter(bin=None)) + + with self.assertNumQueries(1): + list(Test.objects.filter(bin=b'abc')) + with self.assertNumQueries(0 if is_mysql else 1): + list(Test.objects.filter(bin=b'abc')) + + with self.assertNumQueries(1): + list(Test.objects.filter(bin=b'def')) + with self.assertNumQueries(0 if is_mysql else 1): + list(Test.objects.filter(bin=b'def'))