diff --git a/django/forms/widgets.py b/django/forms/widgets.py index 3d7f711056..f48f84dfa8 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -372,7 +372,7 @@ class ClearableFileInput(FileInput): """ Return whether value is considered to be initial value. """ - return bool(value and hasattr(value, 'url')) + return bool(value and getattr(value, 'url', False)) def get_template_substitution_values(self, value): """ diff --git a/tests/forms_tests/widget_tests/test_clearablefileinput.py b/tests/forms_tests/widget_tests/test_clearablefileinput.py index 4982a6e570..5c093dbd46 100644 --- a/tests/forms_tests/widget_tests/test_clearablefileinput.py +++ b/tests/forms_tests/widget_tests/test_clearablefileinput.py @@ -105,3 +105,42 @@ class ClearableFileInputTest(WidgetTest): name='myfile', ) self.assertEqual(value, field) + + def test_html_does_not_mask_exceptions(self): + """ + A ClearableFileInput should not mask exceptions produced while + checking that it has a value. + """ + @python_2_unicode_compatible + class FailingURLFieldFile(object): + @property + def url(self): + raise ValueError('Canary') + + def __str__(self): + return 'value' + + with self.assertRaisesMessage(ValueError, 'Canary'): + self.widget.render('myfile', FailingURLFieldFile()) + + def test_url_as_property(self): + @python_2_unicode_compatible + class URLFieldFile(object): + @property + def url(self): + return 'https://www.python.org/' + + def __str__(self): + return 'value' + + html = self.widget.render('myfile', URLFieldFile()) + self.assertInHTML('value', html) + + def test_return_false_if_url_does_not_exists(self): + @python_2_unicode_compatible + class NoURLFieldFile(object): + def __str__(self): + return 'value' + + html = self.widget.render('myfile', NoURLFieldFile()) + self.assertHTMLEqual(html, '')