diff --git a/django/forms/fields.py b/django/forms/fields.py index ad94ea4740..370f78e8b5 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -20,7 +20,7 @@ from django.forms.boundfield import BoundField from django.forms.utils import from_current_timezone, to_current_timezone from django.forms.widgets import ( FILE_INPUT_CONTRADICTION, CheckboxInput, ClearableFileInput, DateInput, - DateTimeInput, EmailInput, HiddenInput, MultipleHiddenInput, + DateTimeInput, EmailInput, FileInput, HiddenInput, MultipleHiddenInput, NullBooleanSelect, NumberInput, Select, SelectMultiple, SplitDateTimeWidget, SplitHiddenDateTimeWidget, TextInput, TimeInput, URLInput, @@ -646,6 +646,12 @@ class ImageField(FileField): f.seek(0) return f + def widget_attrs(self, widget): + attrs = super().widget_attrs(widget) + if isinstance(widget, FileInput) and 'accept' not in widget.attrs: + attrs.setdefault('accept', 'image/*') + return attrs + class URLField(CharField): widget = URLInput diff --git a/docs/releases/2.1.txt b/docs/releases/2.1.txt index 8ad64f250a..87181fb33d 100644 --- a/docs/releases/2.1.txt +++ b/docs/releases/2.1.txt @@ -166,7 +166,8 @@ File Uploads Forms ~~~~~ -* ... +* The widget for ``ImageField`` now renders with the HTML attribute + ``accept="image/*"``. Generic Views ~~~~~~~~~~~~~ diff --git a/tests/forms_tests/field_tests/test_imagefield.py b/tests/forms_tests/field_tests/test_imagefield.py index 0a0f60440e..e38abc332d 100644 --- a/tests/forms_tests/field_tests/test_imagefield.py +++ b/tests/forms_tests/field_tests/test_imagefield.py @@ -2,9 +2,13 @@ import os import unittest from django.core.files.uploadedfile import SimpleUploadedFile -from django.forms import ImageField, ValidationError +from django.forms import ( + ClearableFileInput, FileInput, ImageField, ValidationError, Widget, +) from django.test import SimpleTestCase +from . import FormFieldAssertionsMixin + try: from PIL import Image except ImportError: @@ -16,7 +20,7 @@ def get_img_path(path): @unittest.skipUnless(Image, "Pillow is required to test ImageField") -class ImageFieldTest(SimpleTestCase): +class ImageFieldTest(FormFieldAssertionsMixin, SimpleTestCase): def test_imagefield_annotate_with_image_after_clean(self): f = ImageField() @@ -64,3 +68,21 @@ class ImageFieldTest(SimpleTestCase): img_file = SimpleUploadedFile('1x1.txt', img_data) with self.assertRaisesMessage(ValidationError, "File extension 'txt' is not allowed."): f.clean(img_file) + + def test_widget_attrs_default_accept(self): + f = ImageField() + # Nothing added for non-FileInput widgets. + self.assertEqual(f.widget_attrs(Widget()), {}) + self.assertEqual(f.widget_attrs(FileInput()), {'accept': 'image/*'}) + self.assertEqual(f.widget_attrs(ClearableFileInput()), {'accept': 'image/*'}) + self.assertWidgetRendersTo(f, '') + + def test_widge_attrs_accept_specified(self): + f = ImageField(widget=FileInput(attrs={'accept': 'image/png'})) + self.assertEqual(f.widget_attrs(f.widget), {}) + self.assertWidgetRendersTo(f, '') + + def test_widge_attrs_accept_false(self): + f = ImageField(widget=FileInput(attrs={'accept': False})) + self.assertEqual(f.widget_attrs(f.widget), {}) + self.assertWidgetRendersTo(f, '')