فهرست منبع

Fixed #19215 -- Fixed rendering ClearableFileInput when editing with invalid files.

Thanks Michael Cardillo for the initial patch.
Marcelo Galigniana 2 سال پیش
والد
کامیت
c0fc1b5302
4فایلهای تغییر یافته به همراه65 افزوده شده و 4 حذف شده
  1. 2 4
      django/forms/fields.py
  2. 8 0
      tests/admin_widgets/models.py
  3. 53 0
      tests/admin_widgets/tests.py
  4. 2 0
      tests/admin_widgets/widgetadmin.py

+ 2 - 4
django/forms/fields.py

@@ -677,10 +677,8 @@ class FileField(Field):
             return initial
         return super().clean(data)
 
-    def bound_data(self, data, initial):
-        if data in (None, FILE_INPUT_CONTRADICTION):
-            return initial
-        return data
+    def bound_data(self, _, initial):
+        return initial
 
     def has_changed(self, initial, data):
         return not self.disabled and data is not None

+ 8 - 0
tests/admin_widgets/models.py

@@ -1,8 +1,13 @@
+import tempfile
 import uuid
 
 from django.contrib.auth.models import User
+from django.core.files.storage import FileSystemStorage
 from django.db import models
 
+temp_storage_dir = tempfile.mkdtemp()
+temp_storage = FileSystemStorage(temp_storage_dir)
+
 
 class MyFileField(models.FileField):
     pass
@@ -177,6 +182,9 @@ class Advisor(models.Model):
 
 class Student(models.Model):
     name = models.CharField(max_length=255)
+    photo = models.ImageField(
+        storage=temp_storage, upload_to="photos", blank=True, null=True
+    )
 
     class Meta:
         ordering = ("name",)

+ 53 - 0
tests/admin_widgets/tests.py

@@ -1772,3 +1772,56 @@ class RelatedFieldWidgetSeleniumTests(AdminWidgetSeleniumTestCase):
         profiles = Profile.objects.all()
         self.assertEqual(len(profiles), 1)
         self.assertEqual(profiles[0].user.username, username_value)
+
+
+class ImageFieldWidgetsSeleniumTests(AdminWidgetSeleniumTestCase):
+    def test_clearablefileinput_widget(self):
+        from selenium.webdriver.common.by import By
+
+        self.admin_login(username="super", password="secret", login_url="/")
+        self.selenium.get(
+            self.live_server_url + reverse("admin:admin_widgets_student_add"),
+        )
+
+        photo_input_id = "id_photo"
+        save_and_edit_button_css_selector = "input[value='Save and continue editing']"
+        tests_files_folder = "%s/files" % os.getcwd()
+        clear_checkbox_id = "photo-clear_id"
+
+        def _submit_and_wait():
+            with self.wait_page_loaded():
+                self.selenium.find_element(
+                    By.CSS_SELECTOR, save_and_edit_button_css_selector
+                ).click()
+
+        # Add a student.
+        title_input = self.selenium.find_element(By.ID, "id_name")
+        title_input.send_keys("Joe Doe")
+        photo_input = self.selenium.find_element(By.ID, photo_input_id)
+        photo_input.send_keys(f"{tests_files_folder}/test.png")
+        _submit_and_wait()
+        student = Student.objects.last()
+        self.assertEqual(student.name, "Joe Doe")
+        self.assertEqual(student.photo.name, "photos/test.png")
+        # Uploading non-image files is not supported by Safari with Selenium,
+        # so upload a broken one instead.
+        photo_input = self.selenium.find_element(By.ID, photo_input_id)
+        photo_input.send_keys(f"{tests_files_folder}/brokenimg.png")
+        _submit_and_wait()
+        self.assertEqual(
+            self.selenium.find_element(By.CSS_SELECTOR, ".errorlist li").text,
+            (
+                "Upload a valid image. The file you uploaded was either not an image "
+                "or a corrupted image."
+            ),
+        )
+        # "Currently" with "Clear" checkbox and "Change" still shown.
+        cover_field_row = self.selenium.find_element(By.CSS_SELECTOR, ".field-photo")
+        self.assertIn("Currently", cover_field_row.text)
+        self.assertIn("Change", cover_field_row.text)
+        # "Clear" box works.
+        self.selenium.find_element(By.ID, clear_checkbox_id).click()
+        _submit_and_wait()
+        student.refresh_from_db()
+        self.assertEqual(student.name, "Joe Doe")
+        self.assertEqual(student.photo.name, "")

+ 2 - 0
tests/admin_widgets/widgetadmin.py

@@ -13,6 +13,7 @@ from .models import (
     Profile,
     ReleaseEvent,
     School,
+    Student,
     User,
     VideoStream,
 )
@@ -72,5 +73,6 @@ site.register(Bee)
 site.register(Advisor)
 
 site.register(School, SchoolAdmin)
+site.register(Student)
 
 site.register(Profile)