ソースを参照

Fixed #22539 -- Copied exclude argument in Model.full_clean() to prevent side effects.

Yehonatan Daniv 11 年 前
コミット
e2e4cdba11
3 ファイル変更11 行追加2 行削除
  1. 2 0
      django/db/models/base.py
  2. 2 2
      tests/validation/__init__.py
  3. 7 0
      tests/validation/tests.py

+ 2 - 0
django/db/models/base.py

@@ -988,6 +988,8 @@ class Model(six.with_metaclass(ModelBase)):
         errors = {}
         if exclude is None:
             exclude = []
+        else:
+            exclude = list(exclude)
 
         try:
             self.clean_fields(exclude=exclude)

+ 2 - 2
tests/validation/__init__.py

@@ -3,9 +3,9 @@ from django.test import TestCase
 
 
 class ValidationTestCase(TestCase):
-    def assertFailsValidation(self, clean, failed_fields):
+    def assertFailsValidation(self, clean, failed_fields, **kwargs):
         with self.assertRaises(ValidationError) as cm:
-            clean()
+            clean(**kwargs)
         self.assertEqual(sorted(failed_fields), sorted(cm.exception.message_dict))
 
     def assertFieldFailsValidationWithMessage(self, clean, field_name, message):

+ 7 - 0
tests/validation/tests.py

@@ -59,6 +59,13 @@ class BaseModelValidationTests(ValidationTestCase):
         mtv = ModelToValidate(number=10, name='Some Name', slug='##invalid##')
         self.assertFailsValidation(mtv.full_clean, ['slug'])
 
+    def test_full_clean_does_not_mutate_exclude(self):
+        mtv = ModelToValidate(f_with_custom_validator=42)
+        exclude = ['number']
+        self.assertFailsValidation(mtv.full_clean, ['name'], exclude=exclude)
+        self.assertEqual(len(exclude), 1)
+        self.assertEqual(exclude[0], 'number')
+
 
 class ArticleForm(forms.ModelForm):
     class Meta: