[Checkins] SVN: Products.CMFDefault/trunk/Products/CMFDefault/ -
added FileUpload field and widget
Yvo Schubbe
y.2008 at wcm-solutions.de
Fri May 2 06:44:07 EDT 2008
Log message for revision 86084:
- added FileUpload field and widget
- refactored add form code
Changed:
U Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py
U Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt
U Products.CMFDefault/trunk/Products/CMFDefault/formlib/configure.zcml
U Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py
U Products.CMFDefault/trunk/Products/CMFDefault/formlib/schema.py
U Products.CMFDefault/trunk/Products/CMFDefault/formlib/widgets.py
-=-
Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py 2008-05-02 10:43:28 UTC (rev 86083)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py 2008-05-02 10:44:06 UTC (rev 86084)
@@ -16,18 +16,16 @@
"""
from zope.component import adapts
-from zope.component import getUtility
-from zope.component.interfaces import IFactory
from zope.formlib import form
from zope.interface import implements
from zope.interface import Interface
from zope.schema import ASCIILine
-from zope.schema import Bytes
from zope.schema import Text
from zope.schema import TextLine
from Products.CMFDefault.formlib.form import ContentAddFormBase
from Products.CMFDefault.formlib.form import ContentEditFormBase
+from Products.CMFDefault.formlib.schema import FileUpload
from Products.CMFDefault.formlib.schema import ProxyFieldProperty
from Products.CMFDefault.formlib.schema import SchemaAdapterBase
from Products.CMFDefault.interfaces import IMutableFile
@@ -59,7 +57,7 @@
title=_(u'Content type'),
readonly=True)
- upload = Bytes(
+ file = FileUpload(
title=_(u'Upload'),
required=False)
@@ -72,9 +70,10 @@
adapts(IMutableFile)
implements(IFileSchema)
- _upload = ProxyFieldProperty(IFileSchema['upload'], 'data')
+ def _getFile(self):
+ return ''
- def _setUpload(self, value):
+ def _setFile(self, value):
self.context.manage_upload(value)
title = ProxyFieldProperty(IFileSchema['title'], 'Title', 'setTitle')
@@ -83,7 +82,7 @@
description = ProxyFieldProperty(IFileSchema['description'],
'Description', 'setDescription')
format = ProxyFieldProperty(IFileSchema['format'], 'Format')
- upload = property(_upload.__get__, _setUpload)
+ file = property(_getFile, _setFile)
class FileAddView(ContentAddFormBase):
@@ -93,7 +92,7 @@
form_fields = (
form.FormFields(IFileSchema).select('title', 'description') +
- form.FormFields(Bytes(__name__='upload', title=_(u'Upload')),
+ form.FormFields(FileUpload(__name__='file', title=_(u'Upload')),
TextLine(__name__='portal_type', default=u'File'))
)
@@ -102,22 +101,17 @@
self).setUpWidgets(ignore_request=ignore_request)
self.widgets['description'].height = 3
self.widgets['portal_type'].hide = True
- self.widgets['upload'].displayWidth = 60
+ self.widgets['file'].displayWidth = 60
def create(self, data):
- ttool = self._getTool('portal_types')
- fti = ttool.getTypeInfo(data['portal_type'])
- factory = getUtility(IFactory, fti.factory)
- obj = factory('temp_id')
- obj._setPortalTypeName(data['portal_type'])
-
+ obj = super(FileAddView,
+ self).create(dict(id=data['file'].filename,
+ portal_type=data['portal_type']))
adapted = FileSchemaAdapter(obj)
+ adapted.title = data['title']
adapted.language = u''
- adapted.upload = self.request.form['%s.upload' % self.prefix]
- if data['title']:
- adapted.title = data['title']
- if data['description']:
- adapted.description = data['description']
+ adapted.description = data['description']
+ adapted.file = data['file']
return obj
@@ -132,11 +126,4 @@
super(FileEditView,
self).setUpWidgets(ignore_request=ignore_request)
self.widgets['description'].height = 3
- self.widgets['upload'].displayWidth = 60
-
- def _handle_success(self, action, data):
- if data.get('upload'):
- data['upload'] = self.request.form['%s.upload' % self.prefix]
- else:
- del data['upload']
- return super(FileEditView, self)._handle_success(action, data)
+ self.widgets['file'].displayWidth = 60
Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt 2008-05-02 10:43:28 UTC (rev 86083)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt 2008-05-02 10:44:06 UTC (rev 86084)
@@ -32,7 +32,7 @@
True
>>> browser.getControl(name='form.title').value = 'FILE TITLE'
>>> browser.getControl(name='form.description').value = 'FILE DESCRIPTION.'
- >>> ctrl = browser.getControl(name='form.upload')
+ >>> ctrl = browser.getControl(name='form.file')
>>> ctrl.add_file(StringIO('FILE DATA'), 'text/plain', 'myFile')
>>> browser.getControl('[[zope][Add]]').click()
>>> '[[cmf_default][[[cmf_default][File]] added.]]' in browser.contents
@@ -52,8 +52,8 @@
>>> browser.open('http://localhost/site/myFile/@@edit.html')
>>> '[[cmf_default][Edit [[cmf_default][File]]]]' in browser.contents
True
- >>> ctrl = browser.getControl(name='form.upload')
- >>> ctrl.add_file(StringIO('FILE DATA'), 'text/plain', 'test.txt')
+ >>> ctrl = browser.getControl(name='form.file')
+ >>> ctrl.add_file(StringIO('FILE DATA 2'), 'text/plain', 'test.txt')
>>> browser.getControl('[[cmf_default][Change]]').click()
>>> '[[cmf_default][[[cmf_default][File]] changed.]]' in browser.contents
True
Modified: Products.CMFDefault/trunk/Products/CMFDefault/formlib/configure.zcml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/configure.zcml 2008-05-02 10:43:28 UTC (rev 86083)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/configure.zcml 2008-05-02 10:44:06 UTC (rev 86084)
@@ -6,4 +6,9 @@
permission="zope.Public"
/>
+ <adapter
+ factory=".widgets.FileUploadWidget"
+ permission="zope.Public"
+ />
+
</configure>
Modified: Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py 2008-05-02 10:43:28 UTC (rev 86083)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py 2008-05-02 10:44:06 UTC (rev 86084)
@@ -23,6 +23,8 @@
from Products.Five.formlib.formbase import PageDisplayForm
from Products.Five.formlib.formbase import PageForm
from zope.app.container.interfaces import INameChooser
+from zope.component import getUtility
+from zope.component.interfaces import IFactory
from zope.datetime import parseDatetimetz
from zope.formlib import form
from zope.i18n.interfaces import IUserPreferredLanguages
@@ -152,15 +154,18 @@
return self._setRedirect('portal_types',
('object/folderContents', 'object/view'))
+ def create(self, data):
+ id = data.pop('id', '')
+ portal_type = data.pop('portal_type')
+ ttool = self._getTool('portal_types')
+ fti = ttool.getTypeInfo(portal_type)
+ factory = getUtility(IFactory, fti.factory)
+ obj = factory(id=id, **data)
+ obj._setPortalTypeName(portal_type)
+ return obj
+
def add(self, obj):
container = self.context
- upload = self.request.form.get('%s.upload' % self.prefix)
- if upload:
- filename = upload.filename.split('\\')[-1] # for IE
- filename = filename.strip().replace(' ','_')
- else:
- filename = u''
- name = INameChooser(container).chooseName(filename, obj)
#check container constraints
ttool = self._getTool('portal_types')
@@ -171,6 +176,7 @@
self.status = u'Disallowed subobject type: %s' % portal_type
return None
+ name = INameChooser(container).chooseName(obj.getId(), obj)
obj.id = name
container._setObject(name, obj)
Modified: Products.CMFDefault/trunk/Products/CMFDefault/formlib/schema.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/schema.py 2008-05-02 10:43:28 UTC (rev 86083)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/schema.py 2008-05-02 10:44:06 UTC (rev 86084)
@@ -28,7 +28,9 @@
from zope.datetime import parseDatetimetz
from zope.interface import implements
from zope.schema import BytesLine
+from zope.schema import Field
from zope.schema.interfaces import IBytesLine
+from zope.schema.interfaces import IField
from Products.CMFCore.interfaces import IPropertiesTool
from Products.CMFDefault.utils import checkEmailAddress
@@ -74,7 +76,7 @@
elif callable(attribute):
attribute = attribute()
- if self._field._type == str:
+ if self._field._type in (str, None):
return attribute
if isinstance(attribute, str) and inst.encoding:
return attribute.decode(inst.encoding)
@@ -139,3 +141,17 @@
super(EmailLine, self)._validate(value)
checkEmailAddress(value)
return True
+
+
+class IFileUpload(IField):
+
+ """A field for file uploads.
+ """
+
+
+class FileUpload(Field):
+
+ """File upload form field.
+ """
+
+ implements(IFileUpload)
Modified: Products.CMFDefault/trunk/Products/CMFDefault/formlib/widgets.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/widgets.py 2008-05-02 10:43:28 UTC (rev 86083)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/widgets.py 2008-05-02 10:44:06 UTC (rev 86084)
@@ -17,6 +17,7 @@
from zope.app.form import InputWidget
from zope.app.form.browser import BrowserWidget
+from zope.app.form.browser import FileWidget
from zope.app.form.browser import MultiSelectSetWidget
from zope.app.form.browser import RadioWidget
from zope.app.form.browser import TextWidget
@@ -26,6 +27,7 @@
from zope.app.form.interfaces import WidgetInputError
from zope.component import adapts
from zope.component import getUtility
+from zope.i18nmessageid import MessageFactory
from zope.interface import implementsOnly
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.schema import Set
@@ -38,9 +40,12 @@
from Products.CMFDefault.utils import scrubHTML
from Products.CMFDefault.utils import Message as _
from schema import IEmailLine
+from schema import IFileUpload
from vocabulary import SimpleVocabulary
+zope_ = MessageFactory("zope")
+
# generic widgets
def ChoiceRadioWidget(field, request):
@@ -105,6 +110,26 @@
return TupleTextAreaWidget(field, field.value_type, request)
+class FileUploadWidget(FileWidget):
+
+ implementsOnly(IInputWidget)
+ adapts(IFileUpload, IBrowserRequest)
+
+ def _toFieldValue(self, input):
+ if not input:
+ return self.context.missing_value
+ try:
+ filename = input.filename.split('\\')[-1] # for IE
+ input.filename = filename.strip().replace(' ','_')
+ except AttributeError, e:
+ raise ConversionError(zope_('Form input is not a file object'), e)
+ return input
+
+ def hasInput(self):
+ return ((self.required and self.name+".used" in self.request.form) or
+ self.request.form.get(self.name))
+
+
# special widgets
class SubjectInputWidget(InputWidget, BrowserWidget):
More information about the Checkins
mailing list