mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[2.0.x] Fixed #28702 -- Made query lookups for CIText fields use citext.
Backport of f0a68c2511 from master
			
			
This commit is contained in:
		| @@ -4,6 +4,10 @@ __all__ = ['CICharField', 'CIEmailField', 'CIText', 'CITextField'] | ||||
|  | ||||
|  | ||||
| class CIText: | ||||
|  | ||||
|     def get_internal_type(self): | ||||
|         return 'CI' + super().get_internal_type() | ||||
|  | ||||
|     def db_type(self, connection): | ||||
|         return 'citext' | ||||
|  | ||||
|   | ||||
| @@ -77,6 +77,8 @@ class DatabaseOperations(BaseDatabaseOperations): | ||||
|                            'istartswith', 'endswith', 'iendswith', 'regex', 'iregex'): | ||||
|             if internal_type in ('IPAddressField', 'GenericIPAddressField'): | ||||
|                 lookup = "HOST(%s)" | ||||
|             elif internal_type in ('CICharField', 'CIEmailField', 'CITextField'): | ||||
|                 lookup = '%s::citext' | ||||
|             else: | ||||
|                 lookup = "%s::text" | ||||
|  | ||||
|   | ||||
| @@ -107,11 +107,12 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): | ||||
|  | ||||
|     def _alter_field(self, model, old_field, new_field, old_type, new_type, | ||||
|                      old_db_params, new_db_params, strict=False): | ||||
|         # Drop indexes on varchar/text columns that are changing to a different | ||||
|         # type. | ||||
|         # Drop indexes on varchar/text/citext columns that are changing to a | ||||
|         # different type. | ||||
|         if (old_field.db_index or old_field.unique) and ( | ||||
|             (old_type.startswith('varchar') and not new_type.startswith('varchar')) or | ||||
|             (old_type.startswith('text') and not new_type.startswith('text')) | ||||
|             (old_type.startswith('text') and not new_type.startswith('text')) or | ||||
|             (old_type.startswith('citext') and not new_type.startswith('citext')) | ||||
|         ): | ||||
|             index_name = self._create_index_name(model._meta.db_table, [old_field.column], suffix='_like') | ||||
|             self.execute(self._delete_constraint_sql(self.sql_delete_index, model, index_name)) | ||||
|   | ||||
| @@ -24,3 +24,6 @@ Bugfixes | ||||
|  | ||||
| * Fixed crash on SQLite and MySQL when ordering by a filtered subquery that | ||||
|   uses ``nulls_first`` or ``nulls_last`` (:ticket:`28848`). | ||||
|  | ||||
| * Made query lookups for ``CICharField``, ``CIEmailField``, and ``CITextField`` | ||||
|   use a ``citext`` cast (:ticket:`28702`). | ||||
|   | ||||
| @@ -138,6 +138,10 @@ class Tests(TestCase): | ||||
|         for lookup in lookups: | ||||
|             with self.subTest(lookup=lookup): | ||||
|                 self.assertIn('::text', do.lookup_cast(lookup)) | ||||
|         for lookup in lookups: | ||||
|             for field_type in ('CICharField', 'CIEmailField', 'CITextField'): | ||||
|                 with self.subTest(lookup=lookup, field_type=field_type): | ||||
|                     self.assertIn('::citext', do.lookup_cast(lookup, internal_type=field_type)) | ||||
|  | ||||
|     def test_correct_extraction_psycopg2_version(self): | ||||
|         from django.db.backends.postgresql.base import psycopg2_version | ||||
|   | ||||
| @@ -12,6 +12,7 @@ from .models import CITestModel | ||||
|  | ||||
| @modify_settings(INSTALLED_APPS={'append': 'django.contrib.postgres'}) | ||||
| class CITextTestCase(PostgreSQLTestCase): | ||||
|     case_sensitive_lookups = ('contains', 'startswith', 'endswith', 'regex') | ||||
|  | ||||
|     @classmethod | ||||
|     def setUpTestData(cls): | ||||
| @@ -42,3 +43,21 @@ class CITextTestCase(PostgreSQLTestCase): | ||||
|         instance = CITestModel.objects.get() | ||||
|         self.assertEqual(instance.array_field, self.john.array_field) | ||||
|         self.assertTrue(CITestModel.objects.filter(array_field__contains=['joe']).exists()) | ||||
|  | ||||
|     def test_lookups_name_char(self): | ||||
|         for lookup in self.case_sensitive_lookups: | ||||
|             with self.subTest(lookup=lookup): | ||||
|                 query = {'name__{}'.format(lookup): 'john'} | ||||
|                 self.assertSequenceEqual(CITestModel.objects.filter(**query), [self.john]) | ||||
|  | ||||
|     def test_lookups_description_text(self): | ||||
|         for lookup, string in zip(self.case_sensitive_lookups, ('average', 'average joe', 'john', 'Joe.named')): | ||||
|             with self.subTest(lookup=lookup, string=string): | ||||
|                 query = {'description__{}'.format(lookup): string} | ||||
|                 self.assertSequenceEqual(CITestModel.objects.filter(**query), [self.john]) | ||||
|  | ||||
|     def test_lookups_email(self): | ||||
|         for lookup, string in zip(self.case_sensitive_lookups, ('john', 'john', 'john.com', 'john.com')): | ||||
|             with self.subTest(lookup=lookup, string=string): | ||||
|                 query = {'email__{}'.format(lookup): string} | ||||
|                 self.assertSequenceEqual(CITestModel.objects.filter(**query), [self.john]) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user