diff --git a/news/67.feature b/news/67.feature new file mode 100644 index 0000000..ecbdb3a --- /dev/null +++ b/news/67.feature @@ -0,0 +1,12 @@ +Add support for the "accept" attribute on file inputs. + +If the widget's field - if there is one - has the "accept" attribute set (the +`NamedImage` field has `image/*` set by default) then this is rendered as an +`accept` attribute on the file input. + +This would restrict the allowed file types before uploading while still being +checked on the server side. + +Fixes: https://github.com/plone/plone.formwidget.namedfile/issues/66 +Depends on: https://github.com/plone/plone.namedfile/pull/158 +[thet] diff --git a/plone/formwidget/namedfile/file_input.pt b/plone/formwidget/namedfile/file_input.pt index fb3bc0f..6bfb891 100644 --- a/plone/formwidget/namedfile/file_input.pt +++ b/plone/formwidget/namedfile/file_input.pt @@ -130,7 +130,8 @@
- - >> 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,67 @@ stored in the field:: True +Rendering field widgets with constraints on allowed media 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 media types with the `accept` attribute, +like shown here:: + + >>> class IContentConstrained(Interface): + ... file_field = field.NamedFile( + ... title=u"File", + ... accept=("audio/mp3", "audio/flac", ".wav") + ... ) + ... image_field = field.NamedImage( + ... title=u"Image", + ... accept=("image/webp", "image/png", ".jpg") + ... ) + + >>> @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 -------------