Contents:
Extends: zope.component.interfaces.IObjectEvent
an event sent when the entry is completed
There are two content types defined in modules within the ‘content’ package:
Implements a data content entry type for use by the save data adapter.
Multi-purpose content type used by the save data adapter to store form submissions
Implements a PFG action adapter to save form submissions as content type instances.
PFG save data adapter that saves form data to content objects
Custom event implementations.
Demonstrating using the save content adapter.
- add adapter
- select adapter
- test adapter with all fields
- test adapter with(out) avoiding security checks
- test with creating different content types
- event triggering
Being a doctest, we can tell a story here.
First, we must perform some setup. We use the testbrowser that is shipped with Five, as this provides proper Zope 2 integration. Most of the documentation, though, is in the underlying zope.testbrower package.
>>> from Products.Five.testbrowser import Browser
>>> browser = Browser()
>>> browser.handleErrors = False
>>> portal_url = self.portal.absolute_url()
The following is useful when writing and debugging testbrowser tests. It lets us see all error messages in the error_log.
>>> self.portal.error_log._ignored_exceptions = ()
With that in place, we can go to the portal front page and log in. We will do this using the default user from PloneTestCase:
>>> from Products.PloneTestCase.setup import portal_owner, default_password
>>> browser.open(portal_url + '/login')
We have the login portlet, so let’s use that.
>>> browser.getControl(name='__ac_name').value = portal_owner
>>> browser.getControl(name='__ac_password').value = default_password
>>> browser.getControl(name='submit').click()
And we ensure that we get the friendly logged-in message:
>>> "You are now logged in" in browser.contents
True
Add the form
>>> browser.open(self.portal.absolute_url())
>>> browser.getLink('Form Folder').click()
>>> browser.getControl(name="title").value = "test-form"
>>> browser.getControl(name="actionAdapter:list").value = []
>>> browser.getControl("Save").click()
>>> form = self.portal['test-form']
Add the adapter
>>> browser.getLink('Save Data to Content Adapter').click()
>>> browser.getControl(name="title").value = 'results'
>>> browser.getControl(name="dynamicTitle").value = 'string:hello this is my title'
>>> browser.getControl(name="form.button.save").click()
Enable the adapter
>>> browser.getLink(text="test-form").click()
>>> browser.getLink(text="Edit").click()
>>> browser.getControl(name="actionAdapter:list").value = ['results']
>>> browser.getControl("Save").click()
>>> adapter = form['results']
Now, we’ll add all interesting fields to the form.
Checkbox
>>> browser.open(form.absolute_url())
>>> browser.getLink(text="Checkbox Field").click()
>>> browser.getControl(name="title").value = 'checkbox'
>>> browser.getControl("Save").click()
Date/Time
>>> browser.open(form.absolute_url())
>>> browser.getLink(text="Date/Time Field").click()
>>> browser.getControl(name="title").value = 'datetime'
>>> browser.getControl("Save").click()
Decimal Number
>>> browser.open(form.absolute_url())
>>> browser.getLink(text="Decimal Number Field").click()
>>> browser.getControl(name="title").value = 'decimal'
>>> browser.getControl("Save").click()
Lines Field
>>> browser.open(form.absolute_url())
>>> browser.getLink(text="Lines Field").click()
>>> browser.getControl(name="title").value = 'lines'
>>> browser.getControl("Save").click()
Password
>>> browser.open(form.absolute_url())
>>> browser.getLink(text="Password Field").click()
>>> browser.getControl(name="title").value = 'password'
>>> browser.getControl("Save").click()
Rating
>>> browser.open(form.absolute_url())
>>> browser.getLink(text="Rating-Scale Field").click()
>>> browser.getControl(name="title").value = 'rating'
>>> browser.getControl("Save").click()
Selection Field
>>> browser.open(form.absolute_url())
>>> browser.getLink(text="Selection Field").click()
>>> browser.getControl(name="title").value = 'selection'
>>> browser.getControl(name="fgVocabulary:lines").value = 'one\ntwo\nthree'
>>> browser.getControl("Save").click()
Fill out the fields and make sure they get saved.
>>> browser.open(form.absolute_url()) >>> browser.getLink(text="test-form").click() >>> browser.getLink(text="View").click()>>> browser.getControl(name="replyto").value = "foo@bar.com" >>> browser.getControl(name="topic").value = "Hello" >>> browser.getControl(name="comments").value = "This is awesome." >>> browser.getControl(name="checkbox:boolean").value = True>>> browser.getControl(name="datetime_year").value = ['2010'] >>> browser.getControl(name="datetime_month").value = ['01'] >>> browser.getControl(name="datetime_day").value = ['01'] >>> browser.getControl(name="datetime_hour").value = ['01'] >>> browser.getControl(name="datetime_minute").value = ['00'] >>> browser.getControl(name="datetime_ampm").value = ['PM']>>> browser.getControl(name="decimal").value = "1.0" >>> browser.getControl(name="lines:lines").value = "hello" >>> browser.getControl(name="password").value = "mypassword">>> browser.getControl(name="rating.1:record").value = ['Strongly disagree'] >>> browser.getControl(name="rating.2:record").value = ['Strongly agree']>>> browser.getControl(name="selection").value = ["one"]>>> browser.getControl("Submit").click()
Check that the results were saved and go to them.
>>> len(adapter.objectIds()) == 1 True>>> result = adapter.values()[0] >>> browser.open(result.absolute_url())>>> 'foo@bar.com' in browser.contents True>>> 'Hello' in browser.contents True>>> 'This is awesome.' in browser.contents True>>> 'hello this is my title' in browser.contents True>>> schema = result.Schema() >>> schema.get('rating').get(result) {'1': 'Strongly disagree', '2': 'Strongly agree'}
Now let’s make the form public and make sure it still creates the result when not logged in.
>>> browser.open(form.absolute_url()) >>> browser.getLink('Publish').click() >>> browser.open(self.portal.absolute_url() + '/logout')>>> browser.open(form.absolute_url()) >>> browser.getControl(name="replyto").value = "foo1@bar1.com" >>> browser.getControl(name="topic").value = "Hello Again" >>> browser.getControl(name="comments").value = "This is cool." >>> browser.getControl("Submit").click()>>> len(adapter.objectIds()) == 2 True
let’s login and make the adapter not avoid security permissions
>>> browser.open(portal_url + '/login') >>> browser.getControl(name='__ac_name').value = portal_owner >>> browser.getControl(name='__ac_password').value = default_password >>> browser.getControl(name='submit').click()>>> browser.open(adapter.absolute_url()) >>> browser.getLink("Edit").click() >>> browser.getControl(name="avoidSecurityChecks:boolean").value = None >>> browser.getControl(name="form.button.save").click()
We’ll log out again and try submitting the form.
>>> browser.open(self.portal.absolute_url() + '/logout')>>> browser.open(form.absolute_url()) >>> browser.getControl(name="replyto").value = "foo1@bar1.com" >>> browser.getControl(name="topic").value = "Hello Again" >>> browser.getControl(name="comments").value = "This is cool." >>> browser.getControl("Submit").click()>>> len(adapter.objectIds()) == 2 True
Let’s try out the functionality of saving as different content types.
Login first...
>>> browser.open(portal_url + '/login')
>>> browser.getControl(name='__ac_name').value = portal_owner
>>> browser.getControl(name='__ac_password').value = default_password
>>> browser.getControl(name='submit').click()
Next, let’s copy the FormSaveData2ContentEntry entry first and use that.
>>> browser.open(self.portal.absolute_url() + '/portal_types/manage_main')
>>> browser.getControl(name="ids:list").value = ['FormSaveData2ContentEntry']
>>> browser.getControl(name="manage_copyObjects:method").click()
>>> browser.getControl(name="manage_pasteObjects:method").click()
>>> browser.open(self.portal.absolute_url() + '/portal_types/copy_of_FormSaveData2ContentEntry/manage_propertiesForm')
>>> browser.getControl(name="title:string").value = "My New D2C Content Type"
>>> browser.getControl(name="manage_editProperties:method").click()
Now go to the save data adapter and see if the option for the new content type is there.
>>> browser.open(adapter.absolute_url())
>>> browser.getLink("Edit").click()
>>> "My New D2C Content Type" in browser.contents
True
FormSaveData2ContentEntry should be the default value.
>>> browser.getControl(name="entryType").value
['FormSaveData2ContentEntry']
Okay, the new type is there. Let’s use it now.
>>> browser.getControl(name="entryType").value = ["copy_of_FormSaveData2ContentEntry"]
>>> browser.getControl(name="form.button.save").click()
Make sure it saved.
>>> "My New D2C Content Type" in browser.contents True>>> adapter.getEntryType() 'copy_of_FormSaveData2ContentEntry'
Now that the type is selected, try and submit another form and make sure it is of the same type.
>>> browser.open(form.absolute_url()) >>> browser.getControl(name="replyto").value = "foo2@bar2.com" >>> browser.getControl(name="topic").value = "Another One! Yay!" >>> browser.getControl(name="comments").value = "Nice. a new content type" >>> browser.getControl("Submit").click()>>> len(adapter.objectIds()) 3>>> entry = adapter[adapter.objectIds()[-1]] >>> entry.getField('replyto').get(entry) 'foo2@bar2.com'>>> entry.portal_type 'copy_of_FormSaveData2ContentEntry'
Set up an event subscriber to listen to FormSaveData2ContentEntryFinalizedEvent events.
>>> def entry_added_handler(obj, evt):
... print "received event: " + evt.__class__.__name__
Add it to subscriber list:
>>> import zope.component
>>> import zope.component.event
>>> gsm = zope.component.getGlobalSiteManager()
>>> from uwosh.pfg.d2c.interfaces import IFormSaveData2ContentEntry
>>> from uwosh.pfg.d2c.interfaces import IFormSaveData2ContentEntryFinalizedEvent
>>> from uwosh.pfg.d2c.events import FormSaveData2ContentEntryFinalizedEvent
>>> zope.component.provideHandler(entry_added_handler, [IFormSaveData2ContentEntry, IFormSaveData2ContentEntryFinalizedEvent])
Fill in yet another entry form to fire an event.
>>> browser.open(form.absolute_url())
>>> browser.getControl(name="replyto").value = "foo3@bar3.com"
>>> browser.getControl(name="topic").value = "..And yet another.."
>>> browser.getControl(name="comments").value = "We want to send an event"
Our handler gets called when we submit it.
>>> browser.getControl("Submit").click()
received event: FormSaveData2ContentEntryFinalizedEvent