소스 검색

Fixed #34205 -- Fixed Meta.constraints validation crash with ArrayField and __len lookup.

Regression in 88fc9e2826044110b7b22577a227f122fe9c1fb5 that began
manifesting in Django 4.1.
James Gillard 2 년 전
부모
커밋
c5ed884eab
4개의 변경된 파일16개의 추가작업 그리고 2개의 파일을 삭제
  1. 1 0
      AUTHORS
  2. 1 1
      django/contrib/postgres/fields/array.py
  3. 4 1
      docs/releases/4.1.5.txt
  4. 10 0
      tests/postgres_tests/test_constraints.py

+ 1 - 0
AUTHORS

@@ -431,6 +431,7 @@ answer newbie questions, and generally made Django that much better:
     james_027@yahoo.com
     James Aylett
     James Bennett <james@b-list.org>
+    James Gillard <jamesgillard@live.co.uk>
     James Murty
     James Tauber <jtauber@jtauber.com>
     James Timmins <jameshtimmins@gmail.com>

+ 1 - 1
django/contrib/postgres/fields/array.py

@@ -297,7 +297,7 @@ class ArrayLenTransform(Transform):
         return (
             "CASE WHEN %(lhs)s IS NULL THEN NULL ELSE "
             "coalesce(array_length(%(lhs)s, 1), 0) END"
-        ) % {"lhs": lhs}, params
+        ) % {"lhs": lhs}, params * 2
 
 
 @ArrayField.register_lookup

+ 4 - 1
docs/releases/4.1.5.txt

@@ -9,4 +9,7 @@ Django 4.1.5 fixes several bugs in 4.1.4.
 Bugfixes
 ========
 
-* ...
+* Fixed a long standing bug in the ``__len`` lookup for ``ArrayField`` that
+  caused a crash of model validation on
+  :attr:`Meta.constraints <django.db.models.Options.constraints>`
+  (:ticket:`34205`).

+ 10 - 0
tests/postgres_tests/test_constraints.py

@@ -76,6 +76,16 @@ class SchemaTests(PostgreSQLTestCase):
             constraint.validate(IntegerArrayModel, IntegerArrayModel())
         constraint.validate(IntegerArrayModel, IntegerArrayModel(field=[1]))
 
+    def test_check_constraint_array_length(self):
+        constraint = CheckConstraint(
+            check=Q(field__len=1),
+            name="array_length",
+        )
+        msg = f"Constraint “{constraint.name}” is violated."
+        with self.assertRaisesMessage(ValidationError, msg):
+            constraint.validate(IntegerArrayModel, IntegerArrayModel())
+        constraint.validate(IntegerArrayModel, IntegerArrayModel(field=[1]))
+
     def test_check_constraint_daterange_contains(self):
         constraint_name = "dates_contains"
         self.assertNotIn(