mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Fixed #14094 -- Added support for unlimited CharField on PostgreSQL.
Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							78f163a4fb
						
					
				
				
					commit
					7eee1dca42
				
			| @@ -339,7 +339,8 @@ class Command(BaseCommand): | ||||
|  | ||||
|         # Add max_length for all CharFields. | ||||
|         if field_type == "CharField" and row.display_size: | ||||
|             field_params["max_length"] = int(row.display_size) | ||||
|             if (size := int(row.display_size)) and size > 0: | ||||
|                 field_params["max_length"] = size | ||||
|  | ||||
|         if field_type in {"CharField", "TextField"} and row.collation: | ||||
|             field_params["db_collation"] = row.collation | ||||
|   | ||||
| @@ -345,6 +345,9 @@ class BaseDatabaseFeatures: | ||||
|     # Set to (exception, message) if null characters in text are disallowed. | ||||
|     prohibits_null_characters_in_text_exception = None | ||||
|  | ||||
|     # Does the backend support unlimited character columns? | ||||
|     supports_unlimited_charfield = False | ||||
|  | ||||
|     # Collation names for use by the Django test suite. | ||||
|     test_collations = { | ||||
|         "ci": None,  # Case-insensitive. | ||||
|   | ||||
| @@ -80,6 +80,12 @@ from .operations import DatabaseOperations  # NOQA isort:skip | ||||
| from .schema import DatabaseSchemaEditor  # NOQA isort:skip | ||||
|  | ||||
|  | ||||
| def _get_varchar_column(data): | ||||
|     if data["max_length"] is None: | ||||
|         return "varchar" | ||||
|     return "varchar(%(max_length)s)" % data | ||||
|  | ||||
|  | ||||
| class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|     vendor = "postgresql" | ||||
|     display_name = "PostgreSQL" | ||||
| @@ -92,7 +98,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|         "BigAutoField": "bigint", | ||||
|         "BinaryField": "bytea", | ||||
|         "BooleanField": "boolean", | ||||
|         "CharField": "varchar(%(max_length)s)", | ||||
|         "CharField": _get_varchar_column, | ||||
|         "DateField": "date", | ||||
|         "DateTimeField": "timestamp with time zone", | ||||
|         "DecimalField": "numeric(%(max_digits)s, %(decimal_places)s)", | ||||
|   | ||||
| @@ -110,3 +110,4 @@ class DatabaseFeatures(BaseDatabaseFeatures): | ||||
|  | ||||
|     has_bit_xor = property(operator.attrgetter("is_postgresql_14")) | ||||
|     supports_covering_spgist_indexes = property(operator.attrgetter("is_postgresql_14")) | ||||
|     supports_unlimited_charfield = True | ||||
|   | ||||
| @@ -817,9 +817,14 @@ class Field(RegisterLookupMixin): | ||||
|         # exactly which wacky database column type you want to use. | ||||
|         data = self.db_type_parameters(connection) | ||||
|         try: | ||||
|             return connection.data_types[self.get_internal_type()] % data | ||||
|             column_type = connection.data_types[self.get_internal_type()] | ||||
|         except KeyError: | ||||
|             return None | ||||
|         else: | ||||
|             # column_type is either a single-parameter function or a string. | ||||
|             if callable(column_type): | ||||
|                 return column_type(data) | ||||
|             return column_type % data | ||||
|  | ||||
|     def rel_db_type(self, connection): | ||||
|         """ | ||||
| @@ -1130,14 +1135,19 @@ class BooleanField(Field): | ||||
|  | ||||
|  | ||||
| class CharField(Field): | ||||
|     description = _("String (up to %(max_length)s)") | ||||
|  | ||||
|     def __init__(self, *args, db_collation=None, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|         self.db_collation = db_collation | ||||
|         if self.max_length is not None: | ||||
|             self.validators.append(validators.MaxLengthValidator(self.max_length)) | ||||
|  | ||||
|     @property | ||||
|     def description(self): | ||||
|         if self.max_length is not None: | ||||
|             return _("String (up to %(max_length)s)") | ||||
|         else: | ||||
|             return _("String (unlimited)") | ||||
|  | ||||
|     def check(self, **kwargs): | ||||
|         databases = kwargs.get("databases") or [] | ||||
|         return [ | ||||
| @@ -1148,6 +1158,12 @@ class CharField(Field): | ||||
|  | ||||
|     def _check_max_length_attribute(self, **kwargs): | ||||
|         if self.max_length is None: | ||||
|             if ( | ||||
|                 connection.features.supports_unlimited_charfield | ||||
|                 or "supports_unlimited_charfield" | ||||
|                 in self.model._meta.required_db_features | ||||
|             ): | ||||
|                 return [] | ||||
|             return [ | ||||
|                 checks.Error( | ||||
|                     "CharFields must define a 'max_length' attribute.", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user