diff --git a/django/db/backends/postgresql/schema.py b/django/db/backends/postgresql/schema.py index 7687c37fe7..e77915b3b1 100644 --- a/django/db/backends/postgresql/schema.py +++ b/django/db/backends/postgresql/schema.py @@ -38,8 +38,11 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): def quote_value(self, value): if isinstance(value, str): value = value.replace('%', '%%') + adapted = psycopg2.extensions.adapt(value) + if hasattr(adapted, 'encoding'): + adapted.encoding = 'utf8' # getquoted() returns a quoted bytestring of the adapted value. - return psycopg2.extensions.adapt(value).getquoted().decode() + return adapted.getquoted().decode() def _field_indexes_sql(self, model, field): output = super()._field_indexes_sql(model, field) diff --git a/tests/constraints/models.py b/tests/constraints/models.py index 1460673a18..f8a4ebe675 100644 --- a/tests/constraints/models.py +++ b/tests/constraints/models.py @@ -4,6 +4,7 @@ from django.db import models class Product(models.Model): price = models.IntegerField(null=True) discounted_price = models.IntegerField(null=True) + unit = models.CharField(max_length=15, null=True) class Meta: required_db_features = { @@ -31,6 +32,13 @@ class Product(models.Model): ), name='%(app_label)s_price_neq_500_wrap', ), + models.CheckConstraint( + check=models.Q( + models.Q(unit__isnull=True) | + models.Q(unit__in=['μg/mL', 'ng/mL']) + ), + name='unicode_unit_list', + ), ] diff --git a/tests/constraints/tests.py b/tests/constraints/tests.py index d9e91bdf49..2796a0f30b 100644 --- a/tests/constraints/tests.py +++ b/tests/constraints/tests.py @@ -88,6 +88,12 @@ class CheckConstraintTests(TestCase): with self.assertRaises(IntegrityError): Product.objects.create(price=10, discounted_price=20) + @skipUnlessDBFeature('supports_table_check_constraints') + def test_database_constraint_unicode(self): + Product.objects.create(price=10, discounted_price=5, unit='μg/mL') + with self.assertRaises(IntegrityError): + Product.objects.create(price=10, discounted_price=7, unit='l') + @skipUnlessDBFeature('supports_table_check_constraints') def test_database_constraint_expression(self): Product.objects.create(price=999, discounted_price=5)