summaryrefslogtreecommitdiff
path: root/django/db/models/fields
diff options
context:
space:
mode:
Diffstat (limited to 'django/db/models/fields')
-rw-r--r--django/db/models/fields/__init__.py70
1 files changed, 69 insertions, 1 deletions
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 15e69d3704..2bce85beef 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -1002,13 +1002,16 @@ class BooleanField(Field):
class CharField(Field):
description = _("String (up to %(max_length)s)")
- def __init__(self, *args, **kwargs):
+ def __init__(self, *args, db_collation=None, **kwargs):
super().__init__(*args, **kwargs)
+ self.db_collation = db_collation
self.validators.append(validators.MaxLengthValidator(self.max_length))
def check(self, **kwargs):
+ databases = kwargs.get('databases') or []
return [
*super().check(**kwargs),
+ *self._check_db_collation(databases),
*self._check_max_length_attribute(**kwargs),
]
@@ -1033,6 +1036,27 @@ class CharField(Field):
else:
return []
+ def _check_db_collation(self, databases):
+ errors = []
+ for db in databases:
+ if not router.allow_migrate_model(db, self.model):
+ continue
+ connection = connections[db]
+ if not (
+ self.db_collation is None or
+ 'supports_collation_on_charfield' in self.model._meta.required_db_features or
+ connection.features.supports_collation_on_charfield
+ ):
+ errors.append(
+ checks.Error(
+ '%s does not support a database collation on '
+ 'CharFields.' % connection.display_name,
+ obj=self,
+ id='fields.E190',
+ ),
+ )
+ return errors
+
def cast_db_type(self, connection):
if self.max_length is None:
return connection.ops.cast_char_field_without_max_length
@@ -1061,6 +1085,12 @@ class CharField(Field):
defaults.update(kwargs)
return super().formfield(**defaults)
+ def deconstruct(self):
+ name, path, args, kwargs = super().deconstruct()
+ if self.db_collation:
+ kwargs['db_collation'] = self.db_collation
+ return name, path, args, kwargs
+
class CommaSeparatedIntegerField(CharField):
default_validators = [validators.validate_comma_separated_integer_list]
@@ -2074,6 +2104,38 @@ class SmallIntegerField(IntegerField):
class TextField(Field):
description = _("Text")
+ def __init__(self, *args, db_collation=None, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.db_collation = db_collation
+
+ def check(self, **kwargs):
+ databases = kwargs.get('databases') or []
+ return [
+ *super().check(**kwargs),
+ *self._check_db_collation(databases),
+ ]
+
+ def _check_db_collation(self, databases):
+ errors = []
+ for db in databases:
+ if not router.allow_migrate_model(db, self.model):
+ continue
+ connection = connections[db]
+ if not (
+ self.db_collation is None or
+ 'supports_collation_on_textfield' in self.model._meta.required_db_features or
+ connection.features.supports_collation_on_textfield
+ ):
+ errors.append(
+ checks.Error(
+ '%s does not support a database collation on '
+ 'TextFields.' % connection.display_name,
+ obj=self,
+ id='fields.E190',
+ ),
+ )
+ return errors
+
def get_internal_type(self):
return "TextField"
@@ -2096,6 +2158,12 @@ class TextField(Field):
**kwargs,
})
+ def deconstruct(self):
+ name, path, args, kwargs = super().deconstruct()
+ if self.db_collation:
+ kwargs['db_collation'] = self.db_collation
+ return name, path, args, kwargs
+
class TimeField(DateTimeCheckMixin, Field):
empty_strings_allowed = False