diff options
Diffstat (limited to 'parts/django/tests/regressiontests/model_fields')
-rw-r--r-- | parts/django/tests/regressiontests/model_fields/4x8.png | bin | 0 -> 87 bytes | |||
-rw-r--r-- | parts/django/tests/regressiontests/model_fields/8x4.png | bin | 0 -> 87 bytes | |||
-rw-r--r-- | parts/django/tests/regressiontests/model_fields/__init__.py | 0 | ||||
-rw-r--r-- | parts/django/tests/regressiontests/model_fields/imagefield.py | 420 | ||||
-rw-r--r-- | parts/django/tests/regressiontests/model_fields/models.py | 154 | ||||
-rw-r--r-- | parts/django/tests/regressiontests/model_fields/tests.py | 313 |
6 files changed, 887 insertions, 0 deletions
diff --git a/parts/django/tests/regressiontests/model_fields/4x8.png b/parts/django/tests/regressiontests/model_fields/4x8.png Binary files differnew file mode 100644 index 0000000..ffce444 --- /dev/null +++ b/parts/django/tests/regressiontests/model_fields/4x8.png diff --git a/parts/django/tests/regressiontests/model_fields/8x4.png b/parts/django/tests/regressiontests/model_fields/8x4.png Binary files differnew file mode 100644 index 0000000..60e6d69 --- /dev/null +++ b/parts/django/tests/regressiontests/model_fields/8x4.png diff --git a/parts/django/tests/regressiontests/model_fields/__init__.py b/parts/django/tests/regressiontests/model_fields/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/parts/django/tests/regressiontests/model_fields/__init__.py diff --git a/parts/django/tests/regressiontests/model_fields/imagefield.py b/parts/django/tests/regressiontests/model_fields/imagefield.py new file mode 100644 index 0000000..dd79e7a --- /dev/null +++ b/parts/django/tests/regressiontests/model_fields/imagefield.py @@ -0,0 +1,420 @@ +import os +import shutil + +from django.core.files import File +from django.core.files.base import ContentFile +from django.core.files.images import ImageFile +from django.test import TestCase + +from models import Image, Person, PersonWithHeight, PersonWithHeightAndWidth, \ + PersonDimensionsFirst, PersonTwoImages, TestImageFieldFile + + +# If PIL available, do these tests. +if Image: + + from models import temp_storage_dir + + + class ImageFieldTestMixin(object): + """ + Mixin class to provide common functionality to ImageField test classes. + """ + + # Person model to use for tests. + PersonModel = PersonWithHeightAndWidth + # File class to use for file instances. + File = ImageFile + + def setUp(self): + """ + Creates a pristine temp directory (or deletes and recreates if it + already exists) that the model uses as its storage directory. + + Sets up two ImageFile instances for use in tests. + """ + if os.path.exists(temp_storage_dir): + shutil.rmtree(temp_storage_dir) + os.mkdir(temp_storage_dir) + + file_path1 = os.path.join(os.path.dirname(__file__), "4x8.png") + self.file1 = self.File(open(file_path1, 'rb')) + + file_path2 = os.path.join(os.path.dirname(__file__), "8x4.png") + self.file2 = self.File(open(file_path2, 'rb')) + + def tearDown(self): + """ + Removes temp directory and all its contents. + """ + shutil.rmtree(temp_storage_dir) + + def check_dimensions(self, instance, width, height, + field_name='mugshot'): + """ + Asserts that the given width and height values match both the + field's height and width attributes and the height and width fields + (if defined) the image field is caching to. + + Note, this method will check for dimension fields named by adding + "_width" or "_height" to the name of the ImageField. So, the + models used in these tests must have their fields named + accordingly. + + By default, we check the field named "mugshot", but this can be + specified by passing the field_name parameter. + """ + field = getattr(instance, field_name) + # Check height/width attributes of field. + if width is None and height is None: + self.assertRaises(ValueError, getattr, field, 'width') + self.assertRaises(ValueError, getattr, field, 'height') + else: + self.assertEqual(field.width, width) + self.assertEqual(field.height, height) + + # Check height/width fields of model, if defined. + width_field_name = field_name + '_width' + if hasattr(instance, width_field_name): + self.assertEqual(getattr(instance, width_field_name), width) + height_field_name = field_name + '_height' + if hasattr(instance, height_field_name): + self.assertEqual(getattr(instance, height_field_name), height) + + + class ImageFieldTests(ImageFieldTestMixin, TestCase): + """ + Tests for ImageField that don't need to be run with each of the + different test model classes. + """ + + def test_equal_notequal_hash(self): + """ + Bug #9786: Ensure '==' and '!=' work correctly. + Bug #9508: make sure hash() works as expected (equal items must + hash to the same value). + """ + # Create two Persons with different mugshots. + p1 = self.PersonModel(name="Joe") + p1.mugshot.save("mug", self.file1) + p2 = self.PersonModel(name="Bob") + p2.mugshot.save("mug", self.file2) + self.assertEqual(p1.mugshot == p2.mugshot, False) + self.assertEqual(p1.mugshot != p2.mugshot, True) + + # Test again with an instance fetched from the db. + p1_db = self.PersonModel.objects.get(name="Joe") + self.assertEqual(p1_db.mugshot == p2.mugshot, False) + self.assertEqual(p1_db.mugshot != p2.mugshot, True) + + # Instance from db should match the local instance. + self.assertEqual(p1_db.mugshot == p1.mugshot, True) + self.assertEqual(hash(p1_db.mugshot), hash(p1.mugshot)) + self.assertEqual(p1_db.mugshot != p1.mugshot, False) + + def test_instantiate_missing(self): + """ + If the underlying file is unavailable, still create instantiate the + object without error. + """ + p = self.PersonModel(name="Joan") + p.mugshot.save("shot", self.file1) + p = self.PersonModel.objects.get(name="Joan") + path = p.mugshot.path + shutil.move(path, path + '.moved') + p2 = self.PersonModel.objects.get(name="Joan") + + def test_delete_when_missing(self): + """ + Bug #8175: correctly delete an object where the file no longer + exists on the file system. + """ + p = self.PersonModel(name="Fred") + p.mugshot.save("shot", self.file1) + os.remove(p.mugshot.path) + p.delete() + + def test_size_method(self): + """ + Bug #8534: FileField.size should not leave the file open. + """ + p = self.PersonModel(name="Joan") + p.mugshot.save("shot", self.file1) + + # Get a "clean" model instance + p = self.PersonModel.objects.get(name="Joan") + # It won't have an opened file. + self.assertEqual(p.mugshot.closed, True) + + # After asking for the size, the file should still be closed. + _ = p.mugshot.size + self.assertEqual(p.mugshot.closed, True) + + def test_pickle(self): + """ + Tests that ImageField can be pickled, unpickled, and that the + image of the unpickled version is the same as the original. + """ + import pickle + + p = Person(name="Joe") + p.mugshot.save("mug", self.file1) + dump = pickle.dumps(p) + + p2 = Person(name="Bob") + p2.mugshot = self.file1 + + loaded_p = pickle.loads(dump) + self.assertEqual(p.mugshot, loaded_p.mugshot) + + + class ImageFieldTwoDimensionsTests(ImageFieldTestMixin, TestCase): + """ + Tests behavior of an ImageField and its dimensions fields. + """ + + def test_constructor(self): + """ + Tests assigning an image field through the model's constructor. + """ + p = self.PersonModel(name='Joe', mugshot=self.file1) + self.check_dimensions(p, 4, 8) + p.save() + self.check_dimensions(p, 4, 8) + + def test_image_after_constructor(self): + """ + Tests behavior when image is not passed in constructor. + """ + p = self.PersonModel(name='Joe') + # TestImageField value will default to being an instance of its + # attr_class, a TestImageFieldFile, with name == None, which will + # cause it to evaluate as False. + self.assertEqual(isinstance(p.mugshot, TestImageFieldFile), True) + self.assertEqual(bool(p.mugshot), False) + + # Test setting a fresh created model instance. + p = self.PersonModel(name='Joe') + p.mugshot = self.file1 + self.check_dimensions(p, 4, 8) + + def test_create(self): + """ + Tests assigning an image in Manager.create(). + """ + p = self.PersonModel.objects.create(name='Joe', mugshot=self.file1) + self.check_dimensions(p, 4, 8) + + def test_default_value(self): + """ + Tests that the default value for an ImageField is an instance of + the field's attr_class (TestImageFieldFile in this case) with no + name (name set to None). + """ + p = self.PersonModel() + self.assertEqual(isinstance(p.mugshot, TestImageFieldFile), True) + self.assertEqual(bool(p.mugshot), False) + + def test_assignment_to_None(self): + """ + Tests that assigning ImageField to None clears dimensions. + """ + p = self.PersonModel(name='Joe', mugshot=self.file1) + self.check_dimensions(p, 4, 8) + + # If image assigned to None, dimension fields should be cleared. + p.mugshot = None + self.check_dimensions(p, None, None) + + p.mugshot = self.file2 + self.check_dimensions(p, 8, 4) + + def test_field_save_and_delete_methods(self): + """ + Tests assignment using the field's save method and deletion using + the field's delete method. + """ + p = self.PersonModel(name='Joe') + p.mugshot.save("mug", self.file1) + self.check_dimensions(p, 4, 8) + + # A new file should update dimensions. + p.mugshot.save("mug", self.file2) + self.check_dimensions(p, 8, 4) + + # Field and dimensions should be cleared after a delete. + p.mugshot.delete(save=False) + self.assertEqual(p.mugshot, None) + self.check_dimensions(p, None, None) + + def test_dimensions(self): + """ + Checks that dimensions are updated correctly in various situations. + """ + p = self.PersonModel(name='Joe') + + # Dimensions should get set if file is saved. + p.mugshot.save("mug", self.file1) + self.check_dimensions(p, 4, 8) + + # Test dimensions after fetching from database. + p = self.PersonModel.objects.get(name='Joe') + # Bug 11084: Dimensions should not get recalculated if file is + # coming from the database. We test this by checking if the file + # was opened. + self.assertEqual(p.mugshot.was_opened, False) + self.check_dimensions(p, 4, 8) + # After checking dimensions on the image field, the file will have + # opened. + self.assertEqual(p.mugshot.was_opened, True) + # Dimensions should now be cached, and if we reset was_opened and + # check dimensions again, the file should not have opened. + p.mugshot.was_opened = False + self.check_dimensions(p, 4, 8) + self.assertEqual(p.mugshot.was_opened, False) + + # If we assign a new image to the instance, the dimensions should + # update. + p.mugshot = self.file2 + self.check_dimensions(p, 8, 4) + # Dimensions were recalculated, and hence file should have opened. + self.assertEqual(p.mugshot.was_opened, True) + + + class ImageFieldNoDimensionsTests(ImageFieldTwoDimensionsTests): + """ + Tests behavior of an ImageField with no dimension fields. + """ + + PersonModel = Person + + + class ImageFieldOneDimensionTests(ImageFieldTwoDimensionsTests): + """ + Tests behavior of an ImageField with one dimensions field. + """ + + PersonModel = PersonWithHeight + + + class ImageFieldDimensionsFirstTests(ImageFieldTwoDimensionsTests): + """ + Tests behavior of an ImageField where the dimensions fields are + defined before the ImageField. + """ + + PersonModel = PersonDimensionsFirst + + + class ImageFieldUsingFileTests(ImageFieldTwoDimensionsTests): + """ + Tests behavior of an ImageField when assigning it a File instance + rather than an ImageFile instance. + """ + + PersonModel = PersonDimensionsFirst + File = File + + + class TwoImageFieldTests(ImageFieldTestMixin, TestCase): + """ + Tests a model with two ImageFields. + """ + + PersonModel = PersonTwoImages + + def test_constructor(self): + p = self.PersonModel(mugshot=self.file1, headshot=self.file2) + self.check_dimensions(p, 4, 8, 'mugshot') + self.check_dimensions(p, 8, 4, 'headshot') + p.save() + self.check_dimensions(p, 4, 8, 'mugshot') + self.check_dimensions(p, 8, 4, 'headshot') + + def test_create(self): + p = self.PersonModel.objects.create(mugshot=self.file1, + headshot=self.file2) + self.check_dimensions(p, 4, 8) + self.check_dimensions(p, 8, 4, 'headshot') + + def test_assignment(self): + p = self.PersonModel() + self.check_dimensions(p, None, None, 'mugshot') + self.check_dimensions(p, None, None, 'headshot') + + p.mugshot = self.file1 + self.check_dimensions(p, 4, 8, 'mugshot') + self.check_dimensions(p, None, None, 'headshot') + p.headshot = self.file2 + self.check_dimensions(p, 4, 8, 'mugshot') + self.check_dimensions(p, 8, 4, 'headshot') + + # Clear the ImageFields one at a time. + p.mugshot = None + self.check_dimensions(p, None, None, 'mugshot') + self.check_dimensions(p, 8, 4, 'headshot') + p.headshot = None + self.check_dimensions(p, None, None, 'mugshot') + self.check_dimensions(p, None, None, 'headshot') + + def test_field_save_and_delete_methods(self): + p = self.PersonModel(name='Joe') + p.mugshot.save("mug", self.file1) + self.check_dimensions(p, 4, 8, 'mugshot') + self.check_dimensions(p, None, None, 'headshot') + p.headshot.save("head", self.file2) + self.check_dimensions(p, 4, 8, 'mugshot') + self.check_dimensions(p, 8, 4, 'headshot') + + # We can use save=True when deleting the image field with null=True + # dimension fields and the other field has an image. + p.headshot.delete(save=True) + self.check_dimensions(p, 4, 8, 'mugshot') + self.check_dimensions(p, None, None, 'headshot') + p.mugshot.delete(save=False) + self.check_dimensions(p, None, None, 'mugshot') + self.check_dimensions(p, None, None, 'headshot') + + def test_dimensions(self): + """ + Checks that dimensions are updated correctly in various situations. + """ + p = self.PersonModel(name='Joe') + + # Dimensions should get set for the saved file. + p.mugshot.save("mug", self.file1) + p.headshot.save("head", self.file2) + self.check_dimensions(p, 4, 8, 'mugshot') + self.check_dimensions(p, 8, 4, 'headshot') + + # Test dimensions after fetching from database. + p = self.PersonModel.objects.get(name='Joe') + # Bug 11084: Dimensions should not get recalculated if file is + # coming from the database. We test this by checking if the file + # was opened. + self.assertEqual(p.mugshot.was_opened, False) + self.assertEqual(p.headshot.was_opened, False) + self.check_dimensions(p, 4, 8,'mugshot') + self.check_dimensions(p, 8, 4, 'headshot') + # After checking dimensions on the image fields, the files will + # have been opened. + self.assertEqual(p.mugshot.was_opened, True) + self.assertEqual(p.headshot.was_opened, True) + # Dimensions should now be cached, and if we reset was_opened and + # check dimensions again, the file should not have opened. + p.mugshot.was_opened = False + p.headshot.was_opened = False + self.check_dimensions(p, 4, 8,'mugshot') + self.check_dimensions(p, 8, 4, 'headshot') + self.assertEqual(p.mugshot.was_opened, False) + self.assertEqual(p.headshot.was_opened, False) + + # If we assign a new image to the instance, the dimensions should + # update. + p.mugshot = self.file2 + p.headshot = self.file1 + self.check_dimensions(p, 8, 4, 'mugshot') + self.check_dimensions(p, 4, 8, 'headshot') + # Dimensions were recalculated, and hence file should have opened. + self.assertEqual(p.mugshot.was_opened, True) + self.assertEqual(p.headshot.was_opened, True) diff --git a/parts/django/tests/regressiontests/model_fields/models.py b/parts/django/tests/regressiontests/model_fields/models.py new file mode 100644 index 0000000..45cd223 --- /dev/null +++ b/parts/django/tests/regressiontests/model_fields/models.py @@ -0,0 +1,154 @@ +import os +import tempfile + +# Try to import PIL in either of the two ways it can end up installed. +# Checking for the existence of Image is enough for CPython, but for PyPy, +# you need to check for the underlying modules. + +try: + from PIL import Image, _imaging +except ImportError: + try: + import Image, _imaging + except ImportError: + Image = None + +from django.core.files.storage import FileSystemStorage +from django.db import models +from django.db.models.fields.files import ImageFieldFile, ImageField + + +class Foo(models.Model): + a = models.CharField(max_length=10) + d = models.DecimalField(max_digits=5, decimal_places=3) + +def get_foo(): + return Foo.objects.get(id=1) + +class Bar(models.Model): + b = models.CharField(max_length=10) + a = models.ForeignKey(Foo, default=get_foo) + +class Whiz(models.Model): + CHOICES = ( + ('Group 1', ( + (1,'First'), + (2,'Second'), + ) + ), + ('Group 2', ( + (3,'Third'), + (4,'Fourth'), + ) + ), + (0,'Other'), + ) + c = models.IntegerField(choices=CHOICES, null=True) + +class BigD(models.Model): + d = models.DecimalField(max_digits=38, decimal_places=30) + +class BigS(models.Model): + s = models.SlugField(max_length=255) + +class BigInt(models.Model): + value = models.BigIntegerField() + null_value = models.BigIntegerField(null = True, blank = True) + +class Post(models.Model): + title = models.CharField(max_length=100) + body = models.TextField() + +class NullBooleanModel(models.Model): + nbfield = models.NullBooleanField() + +class BooleanModel(models.Model): + bfield = models.BooleanField() + string = models.CharField(max_length=10, default='abc') + +############################################################################### +# ImageField + +# If PIL available, do these tests. +if Image: + class TestImageFieldFile(ImageFieldFile): + """ + Custom Field File class that records whether or not the underlying file + was opened. + """ + def __init__(self, *args, **kwargs): + self.was_opened = False + super(TestImageFieldFile, self).__init__(*args,**kwargs) + def open(self): + self.was_opened = True + super(TestImageFieldFile, self).open() + + class TestImageField(ImageField): + attr_class = TestImageFieldFile + + # Set up a temp directory for file storage. + temp_storage_dir = tempfile.mkdtemp() + temp_storage = FileSystemStorage(temp_storage_dir) + temp_upload_to_dir = os.path.join(temp_storage.location, 'tests') + + class Person(models.Model): + """ + Model that defines an ImageField with no dimension fields. + """ + name = models.CharField(max_length=50) + mugshot = TestImageField(storage=temp_storage, upload_to='tests') + + class PersonWithHeight(models.Model): + """ + Model that defines an ImageField with only one dimension field. + """ + name = models.CharField(max_length=50) + mugshot = TestImageField(storage=temp_storage, upload_to='tests', + height_field='mugshot_height') + mugshot_height = models.PositiveSmallIntegerField() + + class PersonWithHeightAndWidth(models.Model): + """ + Model that defines height and width fields after the ImageField. + """ + name = models.CharField(max_length=50) + mugshot = TestImageField(storage=temp_storage, upload_to='tests', + height_field='mugshot_height', + width_field='mugshot_width') + mugshot_height = models.PositiveSmallIntegerField() + mugshot_width = models.PositiveSmallIntegerField() + + class PersonDimensionsFirst(models.Model): + """ + Model that defines height and width fields before the ImageField. + """ + name = models.CharField(max_length=50) + mugshot_height = models.PositiveSmallIntegerField() + mugshot_width = models.PositiveSmallIntegerField() + mugshot = TestImageField(storage=temp_storage, upload_to='tests', + height_field='mugshot_height', + width_field='mugshot_width') + + class PersonTwoImages(models.Model): + """ + Model that: + * Defines two ImageFields + * Defines the height/width fields before the ImageFields + * Has a nullalble ImageField + """ + name = models.CharField(max_length=50) + mugshot_height = models.PositiveSmallIntegerField() + mugshot_width = models.PositiveSmallIntegerField() + mugshot = TestImageField(storage=temp_storage, upload_to='tests', + height_field='mugshot_height', + width_field='mugshot_width') + headshot_height = models.PositiveSmallIntegerField( + blank=True, null=True) + headshot_width = models.PositiveSmallIntegerField( + blank=True, null=True) + headshot = TestImageField(blank=True, null=True, + storage=temp_storage, upload_to='tests', + height_field='headshot_height', + width_field='headshot_width') + +############################################################################### diff --git a/parts/django/tests/regressiontests/model_fields/tests.py b/parts/django/tests/regressiontests/model_fields/tests.py new file mode 100644 index 0000000..72a7d4d --- /dev/null +++ b/parts/django/tests/regressiontests/model_fields/tests.py @@ -0,0 +1,313 @@ +import datetime +import unittest +from decimal import Decimal + +import django.test +from django import forms +from django.db import models +from django.core.exceptions import ValidationError + +from models import Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel + +# If PIL available, do these tests. +if Image: + from imagefield import \ + ImageFieldTests, \ + ImageFieldTwoDimensionsTests, \ + ImageFieldNoDimensionsTests, \ + ImageFieldOneDimensionTests, \ + ImageFieldDimensionsFirstTests, \ + ImageFieldUsingFileTests, \ + TwoImageFieldTests + + +class BasicFieldTests(django.test.TestCase): + def test_show_hidden_initial(self): + """ + Regression test for #12913. Make sure fields with choices respect + show_hidden_initial as a kwarg to models.Field.formfield() + """ + choices = [(0, 0), (1, 1)] + model_field = models.Field(choices=choices) + form_field = model_field.formfield(show_hidden_initial=True) + self.assertTrue(form_field.show_hidden_initial) + + form_field = model_field.formfield(show_hidden_initial=False) + self.assertFalse(form_field.show_hidden_initial) + + def test_nullbooleanfield_blank(self): + """ + Regression test for #13071: NullBooleanField should not throw + a validation error when given a value of None. + + """ + nullboolean = NullBooleanModel(nbfield=None) + try: + nullboolean.full_clean() + except ValidationError, e: + self.fail("NullBooleanField failed validation with value of None: %s" % e.messages) + +class DecimalFieldTests(django.test.TestCase): + def test_to_python(self): + f = models.DecimalField(max_digits=4, decimal_places=2) + self.assertEqual(f.to_python(3), Decimal("3")) + self.assertEqual(f.to_python("3.14"), Decimal("3.14")) + self.assertRaises(ValidationError, f.to_python, "abc") + + def test_default(self): + f = models.DecimalField(default=Decimal("0.00")) + self.assertEqual(f.get_default(), Decimal("0.00")) + + def test_format(self): + f = models.DecimalField(max_digits=5, decimal_places=1) + self.assertEqual(f._format(f.to_python(2)), u'2.0') + self.assertEqual(f._format(f.to_python('2.6')), u'2.6') + self.assertEqual(f._format(None), None) + + def test_get_db_prep_lookup(self): + from django.db import connection + f = models.DecimalField(max_digits=5, decimal_places=1) + self.assertEqual(f.get_db_prep_lookup('exact', None, connection=connection), [None]) + + def test_filter_with_strings(self): + """ + We should be able to filter decimal fields using strings (#8023) + """ + Foo.objects.create(id=1, a='abc', d=Decimal("12.34")) + self.assertEqual(list(Foo.objects.filter(d=u'1.23')), []) + + def test_save_without_float_conversion(self): + """ + Ensure decimals don't go through a corrupting float conversion during + save (#5079). + """ + bd = BigD(d="12.9") + bd.save() + bd = BigD.objects.get(pk=bd.pk) + self.assertEqual(bd.d, Decimal("12.9")) + + def test_lookup_really_big_value(self): + """ + Ensure that really big values can be used in a filter statement, even + with older Python versions. + """ + # This should not crash. That counts as a win for our purposes. + Foo.objects.filter(d__gte=100000000000) + +class ForeignKeyTests(django.test.TestCase): + def test_callable_default(self): + """Test the use of a lazy callable for ForeignKey.default""" + a = Foo.objects.create(id=1, a='abc', d=Decimal("12.34")) + b = Bar.objects.create(b="bcd") + self.assertEqual(b.a, a) + +class DateTimeFieldTests(unittest.TestCase): + def test_datetimefield_to_python_usecs(self): + """DateTimeField.to_python should support usecs""" + f = models.DateTimeField() + self.assertEqual(f.to_python('2001-01-02 03:04:05.000006'), + datetime.datetime(2001, 1, 2, 3, 4, 5, 6)) + self.assertEqual(f.to_python('2001-01-02 03:04:05.999999'), + datetime.datetime(2001, 1, 2, 3, 4, 5, 999999)) + + def test_timefield_to_python_usecs(self): + """TimeField.to_python should support usecs""" + f = models.TimeField() + self.assertEqual(f.to_python('01:02:03.000004'), + datetime.time(1, 2, 3, 4)) + self.assertEqual(f.to_python('01:02:03.999999'), + datetime.time(1, 2, 3, 999999)) + +class BooleanFieldTests(unittest.TestCase): + def _test_get_db_prep_lookup(self, f): + from django.db import connection + self.assertEqual(f.get_db_prep_lookup('exact', True, connection=connection), [True]) + self.assertEqual(f.get_db_prep_lookup('exact', '1', connection=connection), [True]) + self.assertEqual(f.get_db_prep_lookup('exact', 1, connection=connection), [True]) + self.assertEqual(f.get_db_prep_lookup('exact', False, connection=connection), [False]) + self.assertEqual(f.get_db_prep_lookup('exact', '0', connection=connection), [False]) + self.assertEqual(f.get_db_prep_lookup('exact', 0, connection=connection), [False]) + self.assertEqual(f.get_db_prep_lookup('exact', None, connection=connection), [None]) + + def _test_to_python(self, f): + self.assertTrue(f.to_python(1) is True) + self.assertTrue(f.to_python(0) is False) + + def test_booleanfield_get_db_prep_lookup(self): + self._test_get_db_prep_lookup(models.BooleanField()) + + def test_nullbooleanfield_get_db_prep_lookup(self): + self._test_get_db_prep_lookup(models.NullBooleanField()) + + def test_booleanfield_to_python(self): + self._test_to_python(models.BooleanField()) + + def test_nullbooleanfield_to_python(self): + self._test_to_python(models.NullBooleanField()) + + def test_booleanfield_choices_blank(self): + """ + Test that BooleanField with choices and defaults doesn't generate a + formfield with the blank option (#9640, #10549). + """ + choices = [(1, u'Si'), (2, 'No')] + f = models.BooleanField(choices=choices, default=1, null=True) + self.assertEqual(f.formfield().choices, [('', '---------')] + choices) + + f = models.BooleanField(choices=choices, default=1, null=False) + self.assertEqual(f.formfield().choices, choices) + + def test_return_type(self): + b = BooleanModel() + b.bfield = True + b.save() + b2 = BooleanModel.objects.get(pk=b.pk) + self.assertTrue(isinstance(b2.bfield, bool)) + self.assertEqual(b2.bfield, True) + + b3 = BooleanModel() + b3.bfield = False + b3.save() + b4 = BooleanModel.objects.get(pk=b3.pk) + self.assertTrue(isinstance(b4.bfield, bool)) + self.assertEqual(b4.bfield, False) + + b = NullBooleanModel() + b.nbfield = True + b.save() + b2 = NullBooleanModel.objects.get(pk=b.pk) + self.assertTrue(isinstance(b2.nbfield, bool)) + self.assertEqual(b2.nbfield, True) + + b3 = NullBooleanModel() + b3.nbfield = False + b3.save() + b4 = NullBooleanModel.objects.get(pk=b3.pk) + self.assertTrue(isinstance(b4.nbfield, bool)) + self.assertEqual(b4.nbfield, False) + + # http://code.djangoproject.com/ticket/13293 + # Verify that when an extra clause exists, the boolean + # conversions are applied with an offset + b5 = BooleanModel.objects.all().extra( + select={'string_length': 'LENGTH(string)'})[0] + self.assertFalse(isinstance(b5.pk, bool)) + +class ChoicesTests(django.test.TestCase): + def test_choices_and_field_display(self): + """ + Check that get_choices and get_flatchoices interact with + get_FIELD_display to return the expected values (#7913). + """ + self.assertEqual(Whiz(c=1).get_c_display(), 'First') # A nested value + self.assertEqual(Whiz(c=0).get_c_display(), 'Other') # A top level value + self.assertEqual(Whiz(c=9).get_c_display(), 9) # Invalid value + self.assertEqual(Whiz(c=None).get_c_display(), None) # Blank value + self.assertEqual(Whiz(c='').get_c_display(), '') # Empty value + +class SlugFieldTests(django.test.TestCase): + def test_slugfield_max_length(self): + """ + Make sure SlugField honors max_length (#9706) + """ + bs = BigS.objects.create(s = 'slug'*50) + bs = BigS.objects.get(pk=bs.pk) + self.assertEqual(bs.s, 'slug'*50) + + +class ValidationTest(django.test.TestCase): + def test_charfield_raises_error_on_empty_string(self): + f = models.CharField() + self.assertRaises(ValidationError, f.clean, "", None) + + def test_charfield_cleans_empty_string_when_blank_true(self): + f = models.CharField(blank=True) + self.assertEqual('', f.clean('', None)) + + def test_integerfield_cleans_valid_string(self): + f = models.IntegerField() + self.assertEqual(2, f.clean('2', None)) + + def test_integerfield_raises_error_on_invalid_intput(self): + f = models.IntegerField() + self.assertRaises(ValidationError, f.clean, "a", None) + + def test_charfield_with_choices_cleans_valid_choice(self): + f = models.CharField(max_length=1, choices=[('a','A'), ('b','B')]) + self.assertEqual('a', f.clean('a', None)) + + def test_charfield_with_choices_raises_error_on_invalid_choice(self): + f = models.CharField(choices=[('a','A'), ('b','B')]) + self.assertRaises(ValidationError, f.clean, "not a", None) + + def test_choices_validation_supports_named_groups(self): + f = models.IntegerField(choices=(('group',((10,'A'),(20,'B'))),(30,'C'))) + self.assertEqual(10, f.clean(10, None)) + + def test_nullable_integerfield_raises_error_with_blank_false(self): + f = models.IntegerField(null=True, blank=False) + self.assertRaises(ValidationError, f.clean, None, None) + + def test_nullable_integerfield_cleans_none_on_null_and_blank_true(self): + f = models.IntegerField(null=True, blank=True) + self.assertEqual(None, f.clean(None, None)) + + def test_integerfield_raises_error_on_empty_input(self): + f = models.IntegerField(null=False) + self.assertRaises(ValidationError, f.clean, None, None) + self.assertRaises(ValidationError, f.clean, '', None) + + def test_charfield_raises_error_on_empty_input(self): + f = models.CharField(null=False) + self.assertRaises(ValidationError, f.clean, None, None) + + def test_datefield_cleans_date(self): + f = models.DateField() + self.assertEqual(datetime.date(2008, 10, 10), f.clean('2008-10-10', None)) + + def test_boolean_field_doesnt_accept_empty_input(self): + f = models.BooleanField() + self.assertRaises(ValidationError, f.clean, None, None) + + +class BigIntegerFieldTests(django.test.TestCase): + def test_limits(self): + # Ensure that values that are right at the limits can be saved + # and then retrieved without corruption. + maxval = 9223372036854775807 + minval = -maxval - 1 + BigInt.objects.create(value=maxval) + qs = BigInt.objects.filter(value__gte=maxval) + self.assertEqual(qs.count(), 1) + self.assertEqual(qs[0].value, maxval) + BigInt.objects.create(value=minval) + qs = BigInt.objects.filter(value__lte=minval) + self.assertEqual(qs.count(), 1) + self.assertEqual(qs[0].value, minval) + + def test_types(self): + b = BigInt(value = 0) + self.assertTrue(isinstance(b.value, (int, long))) + b.save() + self.assertTrue(isinstance(b.value, (int, long))) + b = BigInt.objects.all()[0] + self.assertTrue(isinstance(b.value, (int, long))) + + def test_coercing(self): + BigInt.objects.create(value ='10') + b = BigInt.objects.get(value = '10') + self.assertEqual(b.value, 10) + +class TypeCoercionTests(django.test.TestCase): + """ + Test that database lookups can accept the wrong types and convert + them with no error: especially on Postgres 8.3+ which does not do + automatic casting at the DB level. See #10015. + + """ + def test_lookup_integer_in_charfield(self): + self.assertEquals(Post.objects.filter(title=9).count(), 0) + + def test_lookup_integer_in_textfield(self): + self.assertEquals(Post.objects.filter(body=24).count(), 0) + |