[Checkins] SVN: Products.CMFDefault/trunk/Products/CMFDefault/ -
added file add view
Yvo Schubbe
y.2008 at wcm-solutions.de
Tue Apr 22 08:19:48 EDT 2008
Log message for revision 85591:
- added file add view
Changed:
U Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt
U Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml
U Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py
A Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt
U Products.CMFDefault/trunk/Products/CMFDefault/browser/tests.py
U Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py
U Products.CMFDefault/trunk/Products/CMFDefault/formlib/schema.py
A Products.CMFDefault/trunk/Products/CMFDefault/profiles/views_support/actions.xml
-=-
Modified: Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt 2008-04-22 12:11:58 UTC (rev 85590)
+++ Products.CMFDefault/trunk/Products/CMFDefault/CHANGES.txt 2008-04-22 12:19:47 UTC (rev 85591)
@@ -2,6 +2,10 @@
Products.CMFDefault 2.2.0 (unreleased)
+ - views: Added ContentEditFormBase and FileAddView.
+ This shows how form-driven content creation works. The content is created
+ without using the constructor methods provided by the types tool.
+
- DublinCore: Modified the 'addCreator' implementation.
It no longer depends on the membership tool.
Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml 2008-04-22 12:11:58 UTC (rev 85590)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/configure.zcml 2008-04-22 12:19:47 UTC (rev 85591)
@@ -106,6 +106,14 @@
<adapter factory=".file.FileSchemaAdapter"/>
<browser:page
+ for="Products.CMFCore.interfaces.IFolderish"
+ layer="..interfaces.ICMFDefaultSkin"
+ name="addFile.html"
+ class=".file.FileAddView"
+ permission="cmf.AddPortalContent"
+ />
+
+ <browser:page
for="..interfaces.IMutableFile"
layer="..interfaces.ICMFDefaultSkin"
name="edit.html"
Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py 2008-04-22 12:11:58 UTC (rev 85590)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/file.py 2008-04-22 12:19:47 UTC (rev 85591)
@@ -24,6 +24,7 @@
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 ProxyFieldProperty
from Products.CMFDefault.formlib.schema import SchemaAdapterBase
@@ -38,11 +39,19 @@
title = TextLine(
title=_(u'Title'),
- readonly=True)
+ required=False,
+ missing_value=u'')
+ language = TextLine(
+ title=_(u'Language'),
+ required=False,
+ missing_value=u'',
+ max_length=2)
+
description = Text(
title=_(u'Description'),
- readonly=True)
+ required=False,
+ missing_value=u'')
format = ASCIILine(
title=_(u'Content type'),
@@ -61,20 +70,55 @@
adapts(IMutableFile)
implements(IFileSchema)
- title = ProxyFieldProperty(IFileSchema['title'], 'Title')
+ _upload = ProxyFieldProperty(IFileSchema['upload'], 'data')
+
+ def _setUpload(self, value):
+ self.context.manage_upload(value)
+
+ title = ProxyFieldProperty(IFileSchema['title'], 'Title', 'setTitle')
+ language = ProxyFieldProperty(IFileSchema['language'],
+ 'Language', 'setLanguage')
description = ProxyFieldProperty(IFileSchema['description'],
- 'Description')
+ 'Description', 'setDescription')
format = ProxyFieldProperty(IFileSchema['format'], 'Format')
- upload = ProxyFieldProperty(IFileSchema['upload'],
- 'data', 'manage_upload')
+ upload = property(_upload.__get__, _setUpload)
+class FileAddView(ContentAddFormBase):
+
+ """Add view for IMutableFile.
+ """
+
+ form_fields = (
+ form.FormFields(IFileSchema).select('title', 'description') +
+ form.FormFields(Bytes(__name__='upload', title=_(u'Upload')),
+ TextLine(__name__='portal_type', default=u'File'))
+ )
+
+ def setUpWidgets(self, ignore_request=False):
+ super(FileAddView,
+ self).setUpWidgets(ignore_request=ignore_request)
+ self.widgets['description'].height = 3
+ self.widgets['portal_type'].hide = True
+ self.widgets['upload'].displayWidth = 60
+
+ def finishCreate(self, obj, data):
+ adapted = FileSchemaAdapter(obj)
+ 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']
+ return obj
+
+
class FileEditView(ContentEditFormBase):
"""Edit view for IMutableFile.
"""
- form_fields = form.FormFields(IFileSchema)
+ form_fields = form.FormFields(IFileSchema).omit('language')
def setUpWidgets(self, ignore_request=False):
super(FileEditView,
@@ -83,6 +127,8 @@
self.widgets['upload'].displayWidth = 60
def _handle_success(self, action, data):
- if not data.get('upload'):
+ 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)
Added: Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt (rev 0)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt 2008-04-22 12:19:47 UTC (rev 85591)
@@ -0,0 +1,59 @@
+File Views
+----------
+
+Set up user.
+
+ >>> uf = app.site.acl_users
+ >>> uf._doAddUser('mgr', 'mgrpw', ['Manager'], [])
+
+Create the browser object we'll be using.
+
+ >>> from Products.Five.testbrowser import Browser
+ >>> browser = Browser()
+ >>> browser.handleErrors = False
+ >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Use the add form without input.
+
+ >>> browser.open('http://localhost/site/@@addFile.html')
+ >>> '[[cmf_default][Add [[cmf_default][File]]]]' in browser.contents
+ True
+ >>> browser.getControl('[[zope][Add]]').click()
+ >>> '[[zope][There were errors]]' in browser.contents
+ True
+ >>> '[[zope][Required input is missing.]]' in browser.contents
+ True
+
+Use the add form with valid input.
+
+ >>> from StringIO import StringIO
+ >>> browser.open('http://localhost/site/@@addFile.html')
+ >>> '[[cmf_default][Add [[cmf_default][File]]]]' in browser.contents
+ True
+ >>> browser.getControl(name='form.title').value = 'FILE TITLE'
+ >>> browser.getControl(name='form.description').value = 'FILE DESCRIPTION.'
+ >>> ctrl = browser.getControl(name='form.upload')
+ >>> ctrl.add_file(StringIO('FILE DATA'), 'text/plain', 'myFile')
+ >>> browser.getControl('[[zope][Add]]').click()
+ >>> '[[cmf_default][[[cmf_default][File]] added.]]' in browser.contents
+ True
+
+Use the edit form without input.
+
+ >>> browser.open('http://localhost/site/myFile/@@edit.html')
+ >>> '[[cmf_default][Edit [[cmf_default][File]]]]' in browser.contents
+ True
+ >>> browser.getControl('[[cmf_default][Change]]').click()
+ >>> '[[cmf_default][Nothing to change.]]' in browser.contents
+ True
+
+Use the edit form with valid input.
+
+ >>> 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')
+ >>> browser.getControl('[[cmf_default][Change]]').click()
+ >>> '[[cmf_default][[[cmf_default][File]] changed.]]' in browser.contents
+ True
Property changes on: Products.CMFDefault/trunk/Products/CMFDefault/browser/file.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Products.CMFDefault/trunk/Products/CMFDefault/browser/tests.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/browser/tests.py 2008-04-22 12:11:58 UTC (rev 85590)
+++ Products.CMFDefault/trunk/Products/CMFDefault/browser/tests.py 2008-04-22 12:19:47 UTC (rev 85591)
@@ -32,6 +32,9 @@
s = ZopeTestCase.FunctionalDocFileSuite('document.txt')
s.layer = FunctionalLayer
suite.addTest(s)
+ s = ZopeTestCase.FunctionalDocFileSuite('file.txt')
+ s.layer = FunctionalLayer
+ suite.addTest(s)
return suite
if __name__ == '__main__':
Modified: Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py 2008-04-22 12:11:58 UTC (rev 85590)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/form.py 2008-04-22 12:19:47 UTC (rev 85591)
@@ -19,8 +19,12 @@
from sets import Set
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+from Products.Five.formlib.formbase import PageAddForm
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
@@ -53,7 +57,7 @@
return locales.getLocale(None, None, None)
-class EditFormBase(PageForm, ViewBase):
+class _EditFormMixin(ViewBase):
template = ViewPageTemplateFile('editform.pt')
@@ -92,10 +96,106 @@
self.request.other['portal_status_message'] = message
-class ContentEditFormBase(EditFormBase):
+class EditFormBase(_EditFormMixin, PageForm):
+ pass
+
+
+class ContentAddFormBase(_EditFormMixin, PageAddForm):
+
actions = form.Actions(
form.Action(
+ name='add',
+ label=form._('Add'),
+ condition=form.haveInputWidgets,
+ success='handle_add',
+ failure='handle_failure'),
+ form.Action(
+ name='cancel',
+ label=_(u'Cancel'),
+ success='handle_cancel_success',
+ failure='handle_cancel_failure'))
+
+ description = u''
+
+ @property
+ def label(self):
+ obj_type = self.widgets['portal_type']._getFormValue()
+ obj_type = translate(obj_type, self.context)
+ return _(u'Add ${obj_type}', mapping={'obj_type': obj_type})
+
+ def handle_add(self, action, data):
+ obj = self.createAndAdd(data)
+ if obj is None:
+ if self.status:
+ message = translate(self.status, self.context)
+ self.request.other['portal_status_message'] = message
+ return
+ obj_type = translate(obj.Type(), self.context)
+ message = translate(_(u'${obj_type} added.',
+ mapping={'obj_type': obj_type}), self.context)
+ if isinstance(message, unicode):
+ message = message.encode(self._getBrowserCharset())
+ fti = obj.getTypeInfo()
+ self._nextURL = '%s/%s?%s' % (obj.absolute_url(), fti.immediate_view,
+ make_query(portal_status_message=message))
+
+ def handle_cancel_success(self, action, data):
+ return self._setRedirect('portal_types', 'object/folderContents')
+
+ def handle_cancel_failure(self, action, data, errors):
+ self.status = None
+ return self._setRedirect('portal_types', 'object/folderContents')
+
+ def create(self, data):
+ portal_type = self.request.form['%s.portal_type' % self.prefix]
+
+ #check type exists
+ ttool = self._getTool('portal_types')
+ fti = ttool.getTypeInfo(portal_type)
+ if fti is None:
+ raise ValueError(u'No such content type: %s' % portal_type)
+
+ factory = getUtility(IFactory, fti.factory)
+ obj = factory('temp_id')
+ if hasattr(obj, '_setPortalTypeName'):
+ obj._setPortalTypeName(portal_type)
+
+ return self.finishCreate(obj, data)
+
+ 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')
+ container_ti = ttool.getTypeInfo(container)
+ portal_type = obj.getPortalTypeName()
+ if container_ti is not None and \
+ not container_ti.allowType(portal_type):
+ self.status = u'Disallowed subobject type: %s' % portal_type
+ return None
+
+ obj.id = name
+ container._setObject(name, obj)
+
+ self._finished_add = True
+ return container._getOb(name)
+
+ def nextURL(self):
+ return self._nextURL
+
+
+class ContentEditFormBase(_EditFormMixin, PageForm):
+
+ actions = form.Actions(
+ form.Action(
name='change',
label=_(u'Change'),
validator='handle_validate',
Modified: Products.CMFDefault/trunk/Products/CMFDefault/formlib/schema.py
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/formlib/schema.py 2008-04-22 12:11:58 UTC (rev 85590)
+++ Products.CMFDefault/trunk/Products/CMFDefault/formlib/schema.py 2008-04-22 12:19:47 UTC (rev 85591)
@@ -55,7 +55,7 @@
self._get_name = get_name
self._set_name = set_name
- def __get__(self, inst, klass):
+ def __get__(self, inst, cls=None):
if inst is None:
return self
Added: Products.CMFDefault/trunk/Products/CMFDefault/profiles/views_support/actions.xml
===================================================================
--- Products.CMFDefault/trunk/Products/CMFDefault/profiles/views_support/actions.xml (rev 0)
+++ Products.CMFDefault/trunk/Products/CMFDefault/profiles/views_support/actions.xml 2008-04-22 12:19:47 UTC (rev 85591)
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<object name="portal_actions" meta_type="CMF Actions Tool"
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n">
+ <object name="folder">
+ <object name="add_file" meta_type="CMF Action" i18n:domain="cmf_default">
+ <property name="title" i18n:translate="">Add File</property>
+ <property name="description"
+ i18n:translate="">Add new File object</property>
+ <property name="url_expr">string:${object_url}/addFile.html</property>
+ <property name="icon_expr"></property>
+ <property
+ name="available_expr">python: folder is object and object.getTypeInfo().allowType('File')</property>
+ <property name="permissions">
+ <element value="Add portal content"/>
+ </property>
+ <property name="visible">True</property>
+ </object>
+ </object>
+</object>
Property changes on: Products.CMFDefault/trunk/Products/CMFDefault/profiles/views_support/actions.xml
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the Checkins
mailing list