diff --git a/news/67.feature b/news/67.feature
new file mode 100644
index 0000000..f37367e
--- /dev/null
+++ b/news/67.feature
@@ -0,0 +1,8 @@
+Add support for accept attribute on file input.
+
+If the widget's field - if there is one - has `allowedContentTypes` set (the `NamedImage` field has `image/*` set by default) the allowed content types are rendered as `accept` attribute on the file input.
+
+This already restricts the allowed file types before uploading while still being checked on the server side too.
+
+Fixes: https://github.com/plone/plone.formwidget.namedfile/issues/66
+Depeds on: https://github.com/plone/plone.namedfile/pull/158
diff --git a/plone/formwidget/namedfile/file_input.pt b/plone/formwidget/namedfile/file_input.pt
index fb3bc0f..8def069 100644
--- a/plone/formwidget/namedfile/file_input.pt
+++ b/plone/formwidget/namedfile/file_input.pt
@@ -131,6 +131,7 @@
tal:omit-tag="not:allow_nochange"
>
>> image_widget.extract()
-The rendering is unchanged:
+The rendering is unchanged::
>>> print(file_widget.render())
@@ -284,7 +284,7 @@ At first, there is no value, so the behaviour is much like before::
>>> image_widget.update()
>>> print(image_widget.render())
-
+
However, if we now set a value, we will have the option of keeping it,
@@ -388,6 +388,66 @@ stored in the field::
True
+Rendering field widgets with constraints on allowed content types
+-----------------------------------------------------------------
+
+The NamedImage already has a constraint on `image/*` mime types for files and
+this is also rendered for the input element. See above.
+You can also customize the allowed content types, like shown here::
+
+ >>> class IContentConstrained(Interface):
+ ... file_field = field.NamedFile(
+ ... title=u"File",
+ ... allowedContentTypes=("audio/mp3", "audio/flac")
+ ... )
+ ... image_field = field.NamedImage(
+ ... title=u"Image",
+ ... allowedContentTypes=("image/webp", "image/png")
+ ... )
+
+ >>> @implementer(IContentConstrained, IImageScaleTraversable, IAttributeAnnotatable)
+ ... class ContentConstrained(object):
+ ... def __init__(self, file, image):
+ ... self.file_field = file
+ ... self.image_field = image
+ ... self._p_mtime = DateTime()
+ ... self.path = '/content_constrained'
+ ...
+ ... def absolute_url(self):
+ ... return root_url + self.path
+ ...
+ ... def Title(self):
+ ... return 'A content item'
+
+ >>> content_constrained = ContentConstrained(None, None)
+
+ >>> file_widget_constrained = NamedFileFieldWidget(IContentConstrained['file_field'], make_request())
+ >>> image_widget_constrained = NamedImageFieldWidget(IContentConstrained['image_field'], make_request())
+
+ >>> file_widget_constrained.context = content_constrained
+ >>> image_widget_constrained.context = content_constrained
+
+ >>> file_widget_constrained.id = 'widget.id.file'
+ >>> file_widget_constrained.name = 'widget.name.file'
+
+ >>> image_widget_constrained.id = 'widget.id.image'
+ >>> image_widget_constrained.name = 'widget.name.image'
+
+At first, there is no value, so the behaviour is much like before::
+
+ >>> file_widget_constrained.update()
+ >>> print(file_widget_constrained.render())
+
+
+
+
+ >>> image_widget_constrained.update()
+ >>> print(image_widget_constrained.render())
+
+
+
+
+
Download view
-------------