diff --git a/django/contrib/admin/templates/admin/widgets/clearable_file_input.html b/django/contrib/admin/templates/admin/widgets/clearable_file_input.html
index 327b8ad16a..9fee235819 100644
--- a/django/contrib/admin/templates/admin/widgets/clearable_file_input.html
+++ b/django/contrib/admin/templates/admin/widgets/clearable_file_input.html
@@ -1,6 +1,6 @@
{% if is_initial %}
{{ initial_text }}: {{ widget.value }}{% if not widget.required %}
-{% endif %}
+{% endif %}
{{ input_text }}:{% endif %}
{% if is_initial %}
{% endif %}
diff --git a/docs/releases/1.11.3.txt b/docs/releases/1.11.3.txt
index 5b3b1066a9..7085b02669 100644
--- a/docs/releases/1.11.3.txt
+++ b/docs/releases/1.11.3.txt
@@ -21,3 +21,5 @@ Bugfixes
* Fixed admin's ``FieldListFilter.get_queryset()`` crash on invalid input
(:ticket:`28202`).
+
+* Fixed invalid HTML for a required ``AdminFileWidget`` (:ticket:`28278`).
diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py
index d53ac0b435..bb8f9df63f 100644
--- a/tests/admin_widgets/tests.py
+++ b/tests/admin_widgets/tests.py
@@ -431,6 +431,18 @@ class AdminFileWidgetTests(TestDataMixin, TestCase):
'',
)
+ def test_render_required(self):
+ widget = widgets.AdminFileWidget()
+ widget.is_required = True
+ self.assertHTMLEqual(
+ widget.render('test', self.album.cover_art),
+ 'Currently: albums\hybrid_theory.jpg
'
+ 'Change:
' % {
+ 'STORAGE_URL': default_storage.url(''),
+ },
+ )
+
def test_readonly_fields(self):
"""
File widgets should render as a link when they're marked "read only."