Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
31d4a7c2
Commit
31d4a7c2
authored
Dec 30, 2009
by
Hanno Schlichting
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Backported c107134 from trunk
parent
140ff24e
Changes
35
Show whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
50 additions
and
2005 deletions
+50
-2005
buildout.cfg
buildout.cfg
+1
-1
doc/CHANGES.rst
doc/CHANGES.rst
+6
-0
setup.py
setup.py
+1
-2
src/Products/Five/TODO.txt
src/Products/Five/TODO.txt
+0
-2
src/Products/Five/browser/tests/pages.txt
src/Products/Five/browser/tests/pages.txt
+1
-1
src/Products/Five/browser/tests/pages.zcml
src/Products/Five/browser/tests/pages.zcml
+0
-9
src/Products/Five/browser/tests/pages_ftest.txt
src/Products/Five/browser/tests/pages_ftest.txt
+1
-1
src/Products/Five/doc/formlib.txt
src/Products/Five/doc/formlib.txt
+0
-18
src/Products/Five/form/__init__.py
src/Products/Five/form/__init__.py
+3
-231
src/Products/Five/form/add.pt
src/Products/Five/form/add.pt
+0
-74
src/Products/Five/form/configure.zcml
src/Products/Five/form/configure.zcml
+2
-11
src/Products/Five/form/edit.pt
src/Products/Five/form/edit.pt
+0
-69
src/Products/Five/form/macros.py
src/Products/Five/form/macros.py
+2
-22
src/Products/Five/form/meta.zcml
src/Products/Five/form/meta.zcml
+2
-32
src/Products/Five/form/metaconfigure.py
src/Products/Five/form/metaconfigure.py
+6
-218
src/Products/Five/form/objectwidget.pt
src/Products/Five/form/objectwidget.pt
+0
-15
src/Products/Five/form/objectwidget.py
src/Products/Five/form/objectwidget.py
+4
-53
src/Products/Five/form/tests/__init__.py
src/Products/Five/form/tests/__init__.py
+0
-1
src/Products/Five/form/tests/configure.zcml
src/Products/Five/form/tests/configure.zcml
+0
-96
src/Products/Five/form/tests/forms.txt
src/Products/Five/form/tests/forms.txt
+0
-489
src/Products/Five/form/tests/locales/de/LC_MESSAGES/formtest.mo
...oducts/Five/form/tests/locales/de/LC_MESSAGES/formtest.mo
+0
-0
src/Products/Five/form/tests/locales/de/LC_MESSAGES/formtest.po
...oducts/Five/form/tests/locales/de/LC_MESSAGES/formtest.po
+0
-51
src/Products/Five/form/tests/locales/formtest.pot
src/Products/Five/form/tests/locales/formtest.pot
+0
-50
src/Products/Five/form/tests/schemacontent.py
src/Products/Five/form/tests/schemacontent.py
+0
-116
src/Products/Five/form/tests/test_forms.py
src/Products/Five/form/tests/test_forms.py
+0
-68
src/Products/Five/formlib/__init__.py
src/Products/Five/formlib/__init__.py
+1
-1
src/Products/Five/formlib/configure.zcml
src/Products/Five/formlib/configure.zcml
+2
-16
src/Products/Five/formlib/formbase.py
src/Products/Five/formlib/formbase.py
+17
-117
src/Products/Five/formlib/tests/__init__.py
src/Products/Five/formlib/tests/__init__.py
+0
-1
src/Products/Five/formlib/tests/configure.zcml
src/Products/Five/formlib/tests/configure.zcml
+0
-24
src/Products/Five/formlib/tests/content.py
src/Products/Five/formlib/tests/content.py
+0
-65
src/Products/Five/formlib/tests/formlib.txt
src/Products/Five/formlib/tests/formlib.txt
+0
-86
src/Products/Five/formlib/tests/test_formlib.py
src/Products/Five/formlib/tests/test_formlib.py
+0
-25
src/Products/Five/formlib/tests/view.py
src/Products/Five/formlib/tests/view.py
+0
-40
versions.cfg
versions.cfg
+1
-0
No files found.
buildout.cfg
View file @
31d4a7c2
...
@@ -43,6 +43,7 @@ eggs =
...
@@ -43,6 +43,7 @@ eggs =
ExtensionClass
ExtensionClass
Persistence
Persistence
RestrictedPython
RestrictedPython
five.formlib
tempstorage
tempstorage
zLOG
zLOG
zope.annotation
zope.annotation
...
@@ -66,7 +67,6 @@ eggs =
...
@@ -66,7 +67,6 @@ eggs =
zope.event
zope.event
zope.exceptions
zope.exceptions
zope.filerepresentation
zope.filerepresentation
zope.formlib
zope.hookable
zope.hookable
zope.i18n
zope.i18n
zope.i18nmessageid
zope.i18nmessageid
...
...
doc/CHANGES.rst
View file @
31d4a7c2
...
@@ -13,6 +13,12 @@ Bugs Fixed
...
@@ -13,6 +13,12 @@ Bugs Fixed
- Fixed a SyntaxError in utilities/load_site.py script.
- Fixed a SyntaxError in utilities/load_site.py script.
Features Added
++++++++++++++
- Moved zope.formlib / zope.app.form integration into a separate package
called five.formlib.
Zope 2.12.2 (2009-12-22)
Zope 2.12.2 (2009-12-22)
------------------------
------------------------
...
...
setup.py
View file @
31d4a7c2
...
@@ -94,6 +94,7 @@ params = dict(name='Zope2',
...
@@ -94,6 +94,7 @@ params = dict(name='Zope2',
'ZConfig'
,
'ZConfig'
,
'ZODB3'
,
'ZODB3'
,
'docutils'
,
'docutils'
,
'five.formlib'
,
'pytz'
,
'pytz'
,
'setuptools'
,
'setuptools'
,
'tempstorage'
,
'tempstorage'
,
...
@@ -108,7 +109,6 @@ params = dict(name='Zope2',
...
@@ -108,7 +109,6 @@ params = dict(name='Zope2',
'zope.deferredimport'
,
'zope.deferredimport'
,
'zope.event'
,
'zope.event'
,
'zope.exceptions'
,
'zope.exceptions'
,
'zope.formlib'
,
'zope.i18n [zcml]'
,
'zope.i18n [zcml]'
,
'zope.i18nmessageid'
,
'zope.i18nmessageid'
,
'zope.interface'
,
'zope.interface'
,
...
@@ -131,7 +131,6 @@ params = dict(name='Zope2',
...
@@ -131,7 +131,6 @@ params = dict(name='Zope2',
'zope.testing'
,
'zope.testing'
,
'zope.traversing'
,
'zope.traversing'
,
'zope.viewlet'
,
'zope.viewlet'
,
'zope.app.form'
,
'zope.app.publication'
,
'zope.app.publication'
,
'zope.app.publisher'
,
'zope.app.publisher'
,
'zope.app.schema'
,
'zope.app.schema'
,
...
...
src/Products/Five/TODO.txt
View file @
31d4a7c2
...
@@ -32,8 +32,6 @@ v1.3
...
@@ -32,8 +32,6 @@ v1.3
v1.4
v1.4
----
----
- namedtemplate in Five.formlib?
- l10n (philikon)
- l10n (philikon)
- Figure out where add-view redirects should go.
- Figure out where add-view redirects should go.
...
...
src/Products/Five/browser/tests/pages.txt
View file @
31d4a7c2
...
@@ -258,7 +258,7 @@ High-level security
...
@@ -258,7 +258,7 @@ High-level security
>>> protected_view_names = [
>>> protected_view_names = [
... 'eagle.txt', 'falcon.html', 'owl.html', 'flamingo.html',
... 'eagle.txt', 'falcon.html', 'owl.html', 'flamingo.html',
... 'condor.html'
, 'protectededitform.html'
]
... 'condor.html']
>>>
>>>
>>> public_view_names = [
>>> public_view_names = [
... 'public_attribute_page',
... 'public_attribute_page',
...
...
src/Products/Five/browser/tests/pages.zcml
View file @
31d4a7c2
...
@@ -233,15 +233,6 @@
...
@@ -233,15 +233,6 @@
permission="zope2.Public"
permission="zope2.Public"
/>
/>
<!-- XXX this should really be in Five.form.tests -->
<!-- protected edit form for permission check -->
<browser:editform
schema="Products.Five.tests.testing.simplecontent.ISimpleContent"
name="protectededitform.html"
permission="zope2.ViewManagementScreens"
/>
<!-- stuff that we'll override in overrides.zcml -->
<!-- stuff that we'll override in overrides.zcml -->
<browser:page
<browser:page
for="Products.Five.tests.testing.simplecontent.ISimpleContent"
for="Products.Five.tests.testing.simplecontent.ISimpleContent"
...
...
src/Products/Five/browser/tests/pages_ftest.txt
View file @
31d4a7c2
...
@@ -60,7 +60,7 @@ those; we start by adding two users:
...
@@ -60,7 +60,7 @@ those; we start by adding two users:
>>> protected_view_names = [
>>> protected_view_names = [
... 'eagle.txt', 'falcon.html', 'owl.html', 'flamingo.html',
... 'eagle.txt', 'falcon.html', 'owl.html', 'flamingo.html',
... 'condor.html'
, 'protectededitform.html'
]
... 'condor.html']
>>>
>>>
>>> public_view_names = [
>>> public_view_names = [
... 'public_attribute_page',
... 'public_attribute_page',
...
...
src/Products/Five/doc/formlib.txt
deleted
100644 → 0
View file @
140ff24e
============================
zope.formlib support in Five
============================
Five supports zope.formlib, an alternative for constructing add, edit, and
other forms based on schema. See zope/formlib/form.txt for a thorough
description of the functionality provided by formlib.
Formlib forms are normal view classes, registered as browser pages. Where
in a pure Zope-3 context you would derive from one of the zope.formlib.form
baseclasses, you now need to derive from one of the baseclasses provided by
Products.Five.formlib.formbase.
In almost all cases you need to import from zope.formlib.from as well -
e.g. Fields and Actions in order to define and select fields and to add
actions to your form.
See Products.Five.formlib.tests for a minimal example.
src/Products/Five/form/__init__.py
View file @
31d4a7c2
##############################################################################
# BBB
#
from
five.formlib
import
AddView
# Copyright (c) 2004, 2005 Zope Corporation and Contributors.
from
five.formlib
import
EditView
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Add and edit views
$Id$
"""
import
sys
from
datetime
import
datetime
import
transaction
from
zope.event
import
notify
from
zope.lifecycleevent
import
ObjectCreatedEvent
,
ObjectModifiedEvent
from
zope.lifecycleevent
import
Attributes
from
zope.location.interfaces
import
ILocation
from
zope.location
import
LocationProxy
from
zope.schema.interfaces
import
ValidationError
from
zope.i18nmessageid
import
MessageFactory
_
=
MessageFactory
(
'zope'
)
from
zope.app.form.browser.submit
import
Update
from
zope.app.form.interfaces
import
IInputWidget
from
zope.app.form.interfaces
import
WidgetsError
from
zope.app.form.utility
import
setUpEditWidgets
,
applyWidgetsChanges
from
zope.app.form.utility
import
setUpWidgets
,
getWidgetsData
from
Products.Five.browser
import
BrowserView
from
Products.Five.browser.decode
import
processInputs
,
setPageEncoding
from
Products.Five.browser.pagetemplatefile
import
ZopeTwoPageTemplateFile
class
EditView
(
BrowserView
):
"""Simple edit-view base class
Subclasses should provide a schema attribute defining the schema
to be edited.
"""
errors
=
()
update_status
=
None
label
=
''
charsets
=
None
# Fall-back field names computes from schema
fieldNames
=
property
(
lambda
self
:
getFieldNamesInOrder
(
self
.
schema
))
# Fall-back template
generated_form
=
ZopeTwoPageTemplateFile
(
'edit.pt'
)
def
__init__
(
self
,
context
,
request
):
BrowserView
.
__init__
(
self
,
context
,
request
)
processInputs
(
self
.
request
,
self
.
charsets
)
setPageEncoding
(
self
.
request
)
self
.
_setUpWidgets
()
def
_setUpWidgets
(
self
):
adapted
=
self
.
schema
(
self
.
context
)
if
adapted
is
not
self
.
context
:
if
not
ILocation
.
providedBy
(
adapted
):
adapted
=
LocationProxy
(
adapted
)
adapted
.
__parent__
=
self
.
context
self
.
adapted
=
adapted
setUpEditWidgets
(
self
,
self
.
schema
,
source
=
self
.
adapted
,
names
=
self
.
fieldNames
)
def
setPrefix
(
self
,
prefix
):
for
widget
in
self
.
widgets
():
widget
.
setPrefix
(
prefix
)
def
widgets
(
self
):
return
[
getattr
(
self
,
name
+
'_widget'
)
for
name
in
self
.
fieldNames
]
def
changed
(
self
):
# This method is overridden to execute logic *after* changes
# have been made.
pass
def
update
(
self
):
if
self
.
update_status
is
not
None
:
# We've been called before. Just return the status we previously
# computed.
return
self
.
update_status
status
=
''
content
=
self
.
adapted
if
Update
in
self
.
request
.
form
.
keys
():
changed
=
False
try
:
changed
=
applyWidgetsChanges
(
self
,
self
.
schema
,
target
=
content
,
names
=
self
.
fieldNames
)
# We should not generate events when an adapter is used.
# That's the adapter's job. We need to unwrap the objects to
# compare them, as they are wrapped differently.
# Additionally, we can't use Acquisition.aq_base() because
# it strangely returns different objects for these two even
# when they are identical. In particular
# aq_base(self.adapted) != self.adapted.aq_base :-(
if
changed
and
getattr
(
self
.
context
,
'aq_base'
,
self
.
context
)
\
is
getattr
(
self
.
adapted
,
'aq_base'
,
self
.
adapted
):
description
=
Attributes
(
self
.
schema
,
*
self
.
fieldNames
)
notify
(
ObjectModifiedEvent
(
content
,
description
))
except
WidgetsError
,
errors
:
self
.
errors
=
errors
status
=
_
(
"An error occurred."
)
transaction
.
abort
()
else
:
setUpEditWidgets
(
self
,
self
.
schema
,
source
=
self
.
adapted
,
ignoreStickyValues
=
True
,
names
=
self
.
fieldNames
)
if
changed
:
self
.
changed
()
formatter
=
self
.
request
.
locale
.
dates
.
getFormatter
(
'dateTime'
,
'medium'
)
status
=
_
(
"Updated on ${date_time}"
,
mapping
=
{
'date_time'
:
formatter
.
format
(
datetime
.
utcnow
())})
self
.
update_status
=
status
return
status
class
AddView
(
EditView
):
"""Simple edit-view base class.
Subclasses should provide a schema attribute defining the schema
to be edited.
"""
def
_setUpWidgets
(
self
):
setUpWidgets
(
self
,
self
.
schema
,
IInputWidget
,
names
=
self
.
fieldNames
)
def
update
(
self
):
if
self
.
update_status
is
not
None
:
# We've been called before. Just return the previous result.
return
self
.
update_status
if
self
.
request
.
form
.
has_key
(
Update
):
self
.
update_status
=
''
try
:
data
=
getWidgetsData
(
self
,
self
.
schema
,
names
=
self
.
fieldNames
)
self
.
createAndAdd
(
data
)
except
WidgetsError
,
errors
:
self
.
errors
=
errors
self
.
update_status
=
_
(
"An error occurred."
)
return
self
.
update_status
self
.
request
.
response
.
redirect
(
self
.
nextURL
())
return
self
.
update_status
def
create
(
self
,
*
args
,
**
kw
):
"""Do the actual instantiation."""
# hack to please typical Zope 2 factories, which expect id and title
# Any sane schema will use a unicode title, and may fail on a
# non-unicode one.
args
=
(
'tmp_id'
,
u'Temporary title'
)
+
args
return
self
.
_factory
(
*
args
,
**
kw
)
def
createAndAdd
(
self
,
data
):
"""Add the desired object using the data in the data argument.
The data argument is a dictionary with the data entered in the form.
"""
args
=
[]
if
self
.
_arguments
:
for
name
in
self
.
_arguments
:
args
.
append
(
data
[
name
])
kw
=
{}
if
self
.
_keyword_arguments
:
for
name
in
self
.
_keyword_arguments
:
if
name
in
data
:
kw
[
str
(
name
)]
=
data
[
name
]
content
=
self
.
create
(
*
args
,
**
kw
)
adapted
=
self
.
schema
(
content
)
errors
=
[]
if
self
.
_set_before_add
:
for
name
in
self
.
_set_before_add
:
if
name
in
data
:
field
=
self
.
schema
[
name
]
try
:
field
.
set
(
adapted
,
data
[
name
])
except
ValidationError
:
errors
.
append
(
sys
.
exc_info
()[
1
])
if
errors
:
raise
WidgetsError
(
*
errors
)
notify
(
ObjectCreatedEvent
(
content
))
content
=
self
.
add
(
content
)
adapted
=
self
.
schema
(
content
)
if
self
.
_set_after_add
:
for
name
in
self
.
_set_after_add
:
if
name
in
data
:
field
=
self
.
schema
[
name
]
try
:
field
.
set
(
adapted
,
data
[
name
])
except
ValidationError
:
errors
.
append
(
sys
.
exc_info
()[
1
])
# We have modified the object, so we need to publish an
# object-modified event:
description
=
Attributes
(
self
.
schema
,
*
self
.
_set_after_add
)
notify
(
ObjectModifiedEvent
(
content
,
description
))
if
errors
:
raise
WidgetsError
(
*
errors
)
return
content
def
add
(
self
,
content
):
return
self
.
context
.
add
(
content
)
def
nextURL
(
self
):
return
self
.
context
.
nextURL
()
src/Products/Five/form/add.pt
deleted
100644 → 0
View file @
140ff24e
<html
metal:use-macro=
"context/@@standard_macros/page"
i18n:domain=
"zope"
>
<body>
<div
metal:fill-slot=
"body"
>
<div
metal:define-macro=
"addform"
>
<form
action=
"."
tal:attributes=
"action request/URL"
method=
"post"
enctype=
"multipart/form-data"
>
<div
metal:define-macro=
"formbody"
>
<h3
tal:condition=
"view/label"
tal:content=
"view/label"
metal:define-slot=
"heading"
>
Add something
</h3>
<p
tal:define=
"status view/update"
tal:condition=
"status"
tal:content=
"status"
/>
<p
tal:condition=
"view/errors"
i18n:translate=
""
>
There are
<strong
tal:content=
"python:len(view.errors)"
i18n:name=
"num_errors"
>
6
</strong>
input errors.
</p>
<div
metal:define-slot=
"extra_info"
tal:replace=
"nothing"
>
</div>
<div
class=
"row"
metal:define-slot=
"extra_top"
tal:replace=
"nothing"
>
<div
class=
"label"
>
Extra top
</div>
<div
class=
"label"
><input
type=
"text"
style=
"width:100%"
/></div>
</div>
<div
metal:use-macro=
"context/@@form_macros/widget_rows"
/>
<div
class=
"separator"
></div>
<div
class=
"row"
metal:define-slot=
"extra_bottom"
tal:replace=
"nothing"
>
<div
class=
"label"
>
Extra bottom
</div>
<div
class=
"field"
><input
type=
"text"
style=
"width:100%"
/></div>
</div>
<div
class=
"separator"
></div>
</div>
<br/><br/>
<div
class=
"row"
>
<div
class=
"controls"
><hr
/>
<input
type=
'submit'
value=
'Refresh'
i18n:attributes=
'value refresh-button'
/>
<input
type=
'submit'
value=
'Add'
name=
'UPDATE_SUBMIT'
i18n:attributes=
'value add-button'
/>
<span
tal:condition=
"context/nameAllowed|nothing"
tal:omit-tag=
""
>
<b
i18n:translate=
""
>
Object Name
</b>
<input
type=
'text'
name=
'add_input_name'
tal:attributes=
"value context/contentName"
/>
</span>
</div>
</div>
<div
class=
"row"
metal:define-slot=
"extra_buttons"
tal:replace=
"nothing"
>
</div>
<div
class=
"separator"
></div>
</form>
</div>
</div>
</body>
</html>
src/Products/Five/form/configure.zcml
View file @
31d4a7c2
<configure xmlns="http://namespaces.zope.org/zope"
<configure xmlns="http://namespaces.zope.org/zope">
xmlns:browser="http://namespaces.zope.org/browser">
<include package="zope.app.form.browser" />
<include package="five.formlib" />
<browser:page
for="*"
name="form_macros"
permission="zope2.View"
class=".macros.FormMacros"
allowed_interface="zope.interface.common.mapping.IItemMapping"
/>
</configure>
</configure>
\ No newline at end of file
src/Products/Five/form/edit.pt
deleted
100644 → 0
View file @
140ff24e
<tal:tag
condition=
"view/update"
/>
<html
metal:use-macro=
"context/@@standard_macros/view"
i18n:domain=
"zope"
>
<body>
<div
metal:fill-slot=
"body"
>
<div
metal:define-macro=
"body"
>
<form
action=
"."
tal:attributes=
"action request/URL"
method=
"POST"
enctype=
"multipart/form-data"
>
<div
metal:define-macro=
"formbody"
>
<h3
tal:condition=
"view/label"
tal:content=
"view/label"
metal:define-slot=
"heading"
>
Edit something
</h3>
<p
tal:define=
"status view/update"
tal:condition=
"status"
tal:content=
"status"
/>
<p
tal:condition=
"view/errors"
i18n:translate=
""
>
There are
<strong
tal:content=
"python:len(view.errors)"
i18n:name=
"num_errors"
>
6
</strong>
input errors.
</p>
<div
metal:define-slot=
"extra_info"
tal:replace=
"nothing"
>
</div>
<div
class=
"row"
metal:define-slot=
"extra_top"
tal:replace=
"nothing"
>
<div
class=
"label"
>
Extra top
</div>
<div
class=
"field"
><input
type=
"text"
style=
"width:100%"
/></div>
</div>
<div
metal:use-macro=
"context/@@form_macros/widget_rows"
/>
<div
class=
"separator"
></div>
<div
class=
"row"
metal:define-slot=
"extra_bottom"
tal:replace=
"nothing"
>
<div
class=
"label"
>
Extra bottom
</div>
<div
class=
"field"
><input
type=
"text"
style=
"width:100%"
/></div>
</div>
<div
class=
"separator"
></div>
</div>
<div
class=
"row"
>
<div
class=
"controls"
>
<input
type=
"submit"
value=
"Refresh"
i18n:attributes=
"value refresh-button"
/>
<input
type=
"submit"
name=
"UPDATE_SUBMIT"
value=
"Change"
i18n:attributes=
"value submit-button"
/>
</div>
</div>
<div
class=
"row"
metal:define-slot=
"extra_buttons"
tal:replace=
"nothing"
>
</div>
<div
class=
"separator"
></div>
</form>
</div>
</div>
</body>
</html>
src/Products/Five/form/macros.py
View file @
31d4a7c2
##############################################################################
# BBB
#
from
five.formlib.macros
import
FormMacros
# Copyright (c) 2004, 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Form macros
$Id$
"""
from
Products.Five.skin.standardmacros
import
StandardMacros
# copy of zope.app.form.browser.macros.FormMacros
class
FormMacros
(
StandardMacros
):
macro_pages
=
(
'widget_macros'
,
'addform_macros'
)
src/Products/Five/form/meta.zcml
View file @
31d4a7c2
<configure
<configure xmlns="http://namespaces.zope.org/zope">
xmlns="http://namespaces.zope.org/zope"
xmlns:meta="http://namespaces.zope.org/meta">
<meta:directives namespace="http://namespaces.zope.org/browser">
<include package="five.formlib" file="meta.zcml" />
<meta:complexDirective
name="editform"
schema="zope.app.form.browser.metadirectives.IEditFormDirective"
handler=".metaconfigure.EditFormDirective"
>
<meta:subdirective
name="widget"
schema="zope.app.form.browser.metadirectives.IWidgetSubdirective"
/>
</meta:complexDirective>
<meta:complexDirective
name="addform"
schema="zope.app.form.browser.metadirectives.IAddFormDirective"
handler=".metaconfigure.AddFormDirective"
>
<meta:subdirective
name="widget"
schema="zope.app.form.browser.metadirectives.IWidgetSubdirective"
/>
</meta:complexDirective>
</meta:directives>
</configure>
</configure>
src/Products/Five/form/metaconfigure.py
View file @
31d4a7c2
##############################################################################
# BBB
#
from
five.formlib.metaconfigure
import
EditViewFactory
# Copyright (c) 2004, 2005 Zope Corporation and Contributors.
from
five.formlib.metaconfigure
import
FiveFormDirective
# All Rights Reserved.
from
five.formlib.metaconfigure
import
EditFormDirective
#
from
five.formlib.metaconfigure
import
AddViewFactory
# This software is subject to the provisions of the Zope Public License,
from
five.formlib.metaconfigure
import
AddFormDirective
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Edit form directives
$Id$
"""
from
App.class_init
import
InitializeClass
from
ExtensionClass
import
Base
import
zope.component
from
zope.interface
import
Interface
from
zope.i18nmessageid
import
MessageFactory
_
=
MessageFactory
(
'zope'
)
from
zope.app.publisher.browser.menumeta
import
menuItemDirective
from
zope.app.form.browser.metaconfigure
import
BaseFormDirective
from
zope.browser.interfaces
import
IAdding
from
Products.Five.form
import
EditView
,
AddView
from
Products.Five.metaclass
import
makeClass
from
Products.Five.security
import
protectClass
from
Products.Five.browser.pagetemplatefile
import
ZopeTwoPageTemplateFile
from
Products.Five.browser.metaconfigure
import
makeClassForTemplate
def
EditViewFactory
(
name
,
schema
,
label
,
permission
,
layer
,
template
,
default_template
,
bases
,
for_
,
fields
,
fulledit_path
=
None
,
fulledit_label
=
None
,
menu
=
u''
):
class_
=
makeClassForTemplate
(
template
,
globals
(),
used_for
=
schema
,
bases
=
bases
)
class_
.
schema
=
schema
class_
.
label
=
label
class_
.
fieldNames
=
fields
class_
.
fulledit_path
=
fulledit_path
if
fulledit_path
and
(
fulledit_label
is
None
):
fulledit_label
=
"Full edit"
class_
.
fulledit_label
=
fulledit_label
class_
.
generated_form
=
ZopeTwoPageTemplateFile
(
default_template
)
if
layer
is
None
:
layer
=
IDefaultBrowserLayer
s
=
zope
.
component
.
getGlobalSiteManager
()
s
.
registerAdapter
(
class_
,
(
for_
,
layer
),
Interface
,
name
)
# Reminder: the permission we got has already been processed by
# BaseFormDirective, that means that zope.Public has been
# translated to the CheckerPublic object
protectClass
(
class_
,
permission
)
InitializeClass
(
class_
)
class
FiveFormDirective
(
BaseFormDirective
):
def
_processWidgets
(
self
):
if
self
.
_widgets
:
customWidgetsObject
=
makeClass
(
'CustomWidgetsMixin'
,
(
Base
,),
self
.
_widgets
)
self
.
bases
=
self
.
bases
+
(
customWidgetsObject
,)
class
EditFormDirective
(
FiveFormDirective
):
view
=
EditView
default_template
=
'edit.pt'
title
=
_
(
'Edit'
)
def
_handle_menu
(
self
):
if
self
.
menu
:
menuItemDirective
(
self
.
_context
,
self
.
menu
,
self
.
for_
or
self
.
schema
,
'@@'
+
self
.
name
,
self
.
title
,
permission
=
self
.
permission
,
layer
=
self
.
layer
)
def
__call__
(
self
):
self
.
_processWidgets
()
self
.
_handle_menu
()
self
.
_context
.
action
(
discriminator
=
self
.
_discriminator
(),
callable
=
EditViewFactory
,
args
=
self
.
_args
(),
kw
=
{
'menu'
:
self
.
menu
},
)
def
AddViewFactory
(
name
,
schema
,
label
,
permission
,
layer
,
template
,
default_template
,
bases
,
for_
,
fields
,
content_factory
,
arguments
,
keyword_arguments
,
set_before_add
,
set_after_add
,
menu
=
u''
):
class_
=
makeClassForTemplate
(
template
,
globals
(),
used_for
=
schema
,
bases
=
bases
)
class_
.
schema
=
schema
class_
.
label
=
label
class_
.
fieldNames
=
fields
class_
.
_factory
=
content_factory
class_
.
_arguments
=
arguments
class_
.
_keyword_arguments
=
keyword_arguments
class_
.
_set_before_add
=
set_before_add
class_
.
_set_after_add
=
set_after_add
class_
.
generated_form
=
ZopeTwoPageTemplateFile
(
default_template
)
if
layer
is
None
:
layer
=
IDefaultBrowserLayer
s
=
zope
.
component
.
getGlobalSiteManager
()
s
.
registerAdapter
(
class_
,
(
for_
,
layer
),
Interface
,
name
)
# Reminder: the permission we got has already been processed by
# BaseFormDirective, that means that zope.Public has been
# translated to the CheckerPublic object
protectClass
(
class_
,
permission
)
InitializeClass
(
class_
)
class
AddFormDirective
(
FiveFormDirective
):
view
=
AddView
default_template
=
'add.pt'
for_
=
IAdding
# default add form information
description
=
None
content_factory
=
None
arguments
=
None
keyword_arguments
=
None
set_before_add
=
None
set_after_add
=
None
def
_handle_menu
(
self
):
if
self
.
menu
or
self
.
title
:
if
(
not
self
.
menu
)
or
(
not
self
.
title
):
raise
ValueError
(
"If either menu or title are specified, "
"they must both be specified"
)
# Add forms are really for IAdding components, so do not use
# for=self.schema.
menuItemDirective
(
self
.
_context
,
self
.
menu
,
self
.
for_
,
'@@'
+
self
.
name
,
self
.
title
,
permission
=
self
.
permission
,
layer
=
self
.
layer
,
description
=
self
.
description
)
def
_handle_arguments
(
self
,
leftover
=
None
):
schema
=
self
.
schema
fields
=
self
.
fields
arguments
=
self
.
arguments
keyword_arguments
=
self
.
keyword_arguments
set_before_add
=
self
.
set_before_add
set_after_add
=
self
.
set_after_add
if
leftover
is
None
:
leftover
=
fields
if
arguments
:
missing
=
[
n
for
n
in
arguments
if
n
not
in
fields
]
if
missing
:
raise
ValueError
(
"Some arguments are not included in the form"
,
missing
)
optional
=
[
n
for
n
in
arguments
if
not
schema
[
n
].
required
]
if
optional
:
raise
ValueError
(
"Some arguments are optional, use"
" keyword_arguments for them"
,
optional
)
leftover
=
[
n
for
n
in
leftover
if
n
not
in
arguments
]
if
keyword_arguments
:
missing
=
[
n
for
n
in
keyword_arguments
if
n
not
in
fields
]
if
missing
:
raise
ValueError
(
"Some keyword_arguments are not included in the form"
,
missing
)
leftover
=
[
n
for
n
in
leftover
if
n
not
in
keyword_arguments
]
if
set_before_add
:
missing
=
[
n
for
n
in
set_before_add
if
n
not
in
fields
]
if
missing
:
raise
ValueError
(
"Some set_before_add are not included in the form"
,
missing
)
leftover
=
[
n
for
n
in
leftover
if
n
not
in
set_before_add
]
if
set_after_add
:
missing
=
[
n
for
n
in
set_after_add
if
n
not
in
fields
]
if
missing
:
raise
ValueError
(
"Some set_after_add are not included in the form"
,
missing
)
leftover
=
[
n
for
n
in
leftover
if
n
not
in
set_after_add
]
self
.
set_after_add
+=
leftover
else
:
self
.
set_after_add
=
leftover
def
__call__
(
self
):
self
.
_processWidgets
()
self
.
_handle_menu
()
self
.
_handle_arguments
()
self
.
_context
.
action
(
discriminator
=
self
.
_discriminator
(),
callable
=
AddViewFactory
,
args
=
self
.
_args
()
+
(
self
.
content_factory
,
self
.
arguments
,
self
.
keyword_arguments
,
self
.
set_before_add
,
self
.
set_after_add
),
kw
=
{
'menu'
:
self
.
menu
},
)
src/Products/Five/form/objectwidget.pt
deleted
100644 → 0
View file @
140ff24e
<fieldset>
<legend tal:content="context/legendTitle"
i18n:translate="">The Legend</legend>
<div class="row" tal:repeat="widget context/subwidgets">
<tal:comment condition="nothing">
This is why we have to duplicate this template: we want to look
up the @@form_macros browser page from something that's
definitely five:traversable (it doesn't really matter where we
look it up, just *that* we look it up); we know the object we're
editing is five:traversable, so we just use that. Yes, three
times context. Weird, eh?
</tal:comment>
<metal:block use-macro="context/context/context/@@form_macros/widget_row" />
</div>
</fieldset>
src/Products/Five/form/objectwidget.py
View file @
31d4a7c2
##############################################################################
# BBB
#
from
five.formlib.objectwidget
import
ObjectWidgetView
# Copyright (c) 2005 Zope Corporation and Contributors.
from
five.formlib.objectwidget
import
ObjectWidget
# All Rights Reserved.
from
five.formlib.objectwidget
import
ObjectWidgetClass
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Five-compatible version of ObjectWidget
This is needed because ObjectWidget uses ViewPageTemplateFile whose
macro definition is unfortunately incompatible with ZopeTwoPageTemplateFile.
So this subclass uses ZopeTwoPageTemplateFile for the template that renders
the widget's sub-editform.
$Id$
"""
from
AccessControl.SecurityInfo
import
ClassSecurityInfo
from
App.class_init
import
InitializeClass
from
Products.Five.browser.pagetemplatefile
import
ViewPageTemplateFile
from
zope.app.form.browser.objectwidget
import
ObjectWidget
as
OWBase
from
zope.app.form.browser.objectwidget
import
ObjectWidgetView
as
OWVBase
class
ObjectWidgetView
(
OWVBase
):
security
=
ClassSecurityInfo
()
security
.
declareObjectPublic
()
template
=
ViewPageTemplateFile
(
'objectwidget.pt'
)
InitializeClass
(
ObjectWidgetView
)
class
ObjectWidgetClass
(
OWBase
):
def
setRenderedValue
(
self
,
value
):
"""Slightly more robust re-implementation this method."""
# re-call setupwidgets with the content
self
.
_setUpEditWidgets
()
for
name
in
self
.
names
:
val
=
getattr
(
value
,
name
,
None
)
if
val
is
None
:
# this is where we are more robust than Zope 3.2's
# object widget: we supply subwidgets with the default
# from the schema, not None (Zope 3.2's list widget
# breaks when the rendered value is None)
val
=
self
.
context
.
schema
[
name
].
default
self
.
getSubWidget
(
name
).
setRenderedValue
(
val
)
ObjectWidget
=
ObjectWidgetClass
src/Products/Five/form/tests/__init__.py
deleted
100644 → 0
View file @
140ff24e
# import this
src/Products/Five/form/tests/configure.zcml
deleted
100644 → 0
View file @
140ff24e
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:meta="http://namespaces.zope.org/meta"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:five="http://namespaces.zope.org/five"
xmlns:i18n="http://namespaces.zope.org/i18n"
i18n_domain="formtest">
<!-- make the zope2.Public permission work -->
<meta:redefinePermission from="zope2.Public" to="zope.Public" />
<!-- browser forms -->
<browser:editform
schema=".schemacontent.IFieldContent"
for=".schemacontent.IFieldContent"
name="edit.html"
label="Edit Field Content"
permission="zope2.Public"
/>
<browser:editform
schema=".schemacontent.IComplexSchemaContent"
for=".schemacontent.IComplexSchemaContent"
name="edit.html"
permission="zope2.Public"
class=".schemacontent.ComplexSchemaView"
/>
<view
type="zope.publisher.interfaces.browser.IBrowserRequest"
for="zope.schema.interfaces.IObject"
provides="zope.app.form.interfaces.IInputWidget"
factory="Products.Five.form.objectwidget.ObjectWidget"
permission="zope.Public"
/>
<!-- With a widget override -->
<browser:editform
schema=".schemacontent.IFieldContent"
for=".schemacontent.IFieldContent"
name="widgetoverride.html"
permission="zope2.Public"
>
<widget
field="description"
class="zope.app.form.browser.TextAreaWidget"
/>
</browser:editform>
<browser:addform
schema=".schemacontent.IFieldContent"
content_factory=".schemacontent.FieldContent"
name="addfieldcontent.html"
label="Add Field Content"
permission="zope2.Public"
/>
<browser:addform
schema=".schemacontent.IFieldContent"
content_factory=".schemacontent.FieldContent"
name="addwidgetoverride.html"
permission="zope2.Public"
set_before_add="title description somenumber somelist">
<widget
field="description"
class="zope.app.form.browser.TextAreaWidget"
/>
</browser:addform>
<browser:addform
schema=".schemacontent.IFieldContent"
content_factory=".schemacontent.FieldContent"
name="protectedaddform.html"
permission="zope2.ViewManagementScreens"
/>
<subscriber
for=".schemacontent.IFieldContent
zope.lifecycleevent.interfaces.IObjectModifiedEvent"
handler=".schemacontent.modifiedSubscriber"
/>
<subscriber
for=".schemacontent.IFieldContent
zope.lifecycleevent.interfaces.IObjectCreatedEvent"
handler=".schemacontent.createdSubscriber"
/>
<i18n:registerTranslations directory="locales"/>
</configure>
src/Products/Five/form/tests/forms.txt
deleted
100644 → 0
View file @
140ff24e
Testing forms
=============
Before we can begin, we need to set up a few things. We need a
manager account:
>>> uf = self.folder.acl_users
>>> uf._doAddUser('manager', 'r00t', ['Manager'], [])
We need to configure all of Five for the functional test:
>>> import Products.Five.form.tests
>>> from Products.Five import zcml
>>> zcml.load_config('configure.zcml', package=Products.Five)
>>> zcml.load_config('configure.zcml', package=Products.Five.form.tests)
Finally, we need to setup a traversable folder. Otherwise, Five won't
get to to do its view lookup:
>>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
>>> manage_addFiveTraversableFolder(self.folder, 'ftf')
Let's set up a testbrowser:
>>> from Products.Five.testbrowser import Browser
>>> browser = Browser()
>>> browser.addHeader('Accept-Language', 'en-US')
Add forms
---------
We can add objects to containers (object managers) through add forms.
An unprotected form can be accessed with anonymously:
>>> browser.open("http://localhost/test_folder_1_/ftf/+/addfieldcontent.html")
>>> print browser.headers
Status: 200 ...
...
We don't have access, we will not be able to get to the protected add form:
>>> browser.open("http://localhost/test_folder_1_/ftf/+/protectedaddform.html")
Traceback (most recent call last):
...
HTTPError: HTTP Error 401: Unauthorized
For a protected one we need a manager account:
>>> browser.addHeader('Authorization', 'Basic manager:r00t')
>>> browser.open("http://localhost/test_folder_1_/ftf/+/protectedaddform.html")
>>> print browser.headers
Status: 200 ...
...
Now let's add a piece of our sample content object to test more things
on it:
>>> ctl = browser.getControl(name="field.title")
>>> ctl.value = 'title'
>>> ctl = browser.getControl(name="add_input_name")
>>> ctl.value = 'edittest'
>>> browser.getControl(name="UPDATE_SUBMIT").click()
Having added this piece of content, we can access it under its URL:
>>> browser.open("http://localhost/test_folder_1_/ftf/edittest")
>>> print browser.headers
Status: 200 ...
...
We can also verify that the title was set correctly, and the not
specified attribute is the default value:
>>> edittest = self.folder.ftf.edittest
>>> edittest.title
u'title'
>>> edittest.description #XXX shouldn't we get a u'' here???
We can also verify that the IObjectCreatedEvent was fired, and the test
subscriber we registered set a flag indicating such:
>>> edittest._created_flag
True
Because the process of adding an object often sets attributes after the
object is created and added, and IObjectModified event should also have been
fired:
>>> edittest._modified_flag
True
>>> del edittest._modified_flag
Edit forms
----------
First, it's important to note that forms validate user input.
Therefore, if we specify invalid data, our object won't change:
>>> browser.open("http://localhost/test_folder_1_/ftf/edittest/@@edit.html")
>>> ctl = browser.getControl(name="field.title")
>>> ctl.value = ''
>>> ctl = browser.getControl(name="field.description")
>>> ctl.value = 'BarDescription'
>>> browser.getControl(name="UPDATE_SUBMIT").click()
>>> print browser.headers
Status: 200 ...
...
>>> print browser.contents
<html>
...
There are <strong>1</strong> input errors.
...
We will see that nothing has changed:
>>> edittest.title
u'title'
>>> edittest.description #XXX shouldn't we get a u'' here???
>>> getattr(edittest, '_modified_flag', False)
False
However, when we specify the correct fields:
>>> browser.open("http://localhost/test_folder_1_/ftf/edittest/@@edit.html")
>>> ctl = browser.getControl(name="field.title")
>>> ctl.value = 'FooTitle'
>>> ctl = browser.getControl(name="field.description")
>>> ctl.value = 'FooDescription'
>>> browser.getControl(name="UPDATE_SUBMIT").click()
>>> print browser.headers
Status: 200 ...
...
We will see that something has changed:
>>> edittest.title
u'FooTitle'
>>> edittest.description
u'FooDescription'
And that the event has been fired:
>>> edittest._modified_flag
True
>>> del edittest._modified_flag
Widget Overrides
----------------
We have an alternate add form for IFieldContent which uses a TextArea widget
via and override in the zcml. Let's ensure that that works:
>>> print http(r"""
... GET /test_folder_1_/ftf/+/addwidgetoverride.html HTTP/1.1
... """, handle_errors=False)
HTTP/1.1 200 OK
...
...<textarea
...
>>> print http(r"""
... POST /test_folder_1_/ftf/+/addwidgetoverride.html HTTP/1.1
... Authorization: Basic manager:r00t
... Content-Type: multipart/form-data; boundary=---------------------------968064918930967154199105236
... Content-Length: 527
...
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.title"
...
... title2
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.description"
...
... Blah
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Add
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="add_input_name"
...
... edittest2
... -----------------------------968064918930967154199105236--
... """, handle_errors=False)
HTTP/1.1 302 Moved Temporarily
...
Location: http://localhost/test_folder_1_/ftf/manage_main
...
We also indicated that all fields for this view should be set before adding
the content, this means that no IObjectModified event should have been fired
>>> edittest2 = self.folder.ftf.edittest2
>>> edittest2.title
u'title2'
>>> edittest2.description
u'Blah'
>>> edittest2._created_flag
True
>>> getattr(edittest2, '_modified_flag', False)
False
Unicode-safety of forms
-----------------------
Even though ZPublisher does not support unicode, automatically
generated forms do. In the following we will enter the following two
chinese sequences (How do you do? and I'm doing good) in forms
(they're encoded in UTF-8 here):
>>> ni_hao = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> wo_hen_hao = '\346\210\221\345\276\210\345\245\275'
First, it's imaginable that we make a mistake and enter one of the
phrases in the integer field:
>>> print http(r"""
... POST /test_folder_1_/ftf/+/addfieldcontent.html HTTP/1.1
... Authorization: Basic manager:r00t
... Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
... Content-Type: multipart/form-data; boundary=---------------------------968064918930967154199105236
... Content-Length: 418
...
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.title"
...
... ChineseTitle
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.description"
...
... ChineseDescription
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somenumber"
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Add
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="add_input_name"
...
... unicodetest
... -----------------------------968064918930967154199105236--
... """ % ni_hao, handle_errors=False)
HTTP/1.1 200 OK
...
There are <strong>1</strong> input errors.
...
When we enter the unicode data in the right fields (the text fields),
the form will submit correctly and create the object:
>>> print http(r"""
... POST /test_folder_1_/ftf/+/addfieldcontent.html HTTP/1.1
... Authorization: Basic manager:r00t
... Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
... Content-Type: multipart/form-data; boundary=---------------------------968064918930967154199105236
... Content-Length: 418
...
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.title"
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.description"
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somenumber"
...
... 0
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Add
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="add_input_name"
...
... unicodetest
... -----------------------------968064918930967154199105236--
... """ % (ni_hao, wo_hen_hao), handle_errors=False)
HTTP/1.1 302 Moved Temporarily
...
Location: http://localhost/test_folder_1_/ftf/manage_main
...
We can test the object has the correct values, as unicode strings, of
course:
>>> unicodetest = self.folder.ftf.unicodetest
>>> unicodetest.title == ni_hao.decode('utf-8')
True
>>> unicodetest.description == wo_hen_hao.decode('utf-8')
True
>>> unicodetest.somenumber
0
Of course, the same should apply to edit forms. First, we happen to
again make the mistake of entering unicode data in the integer field:
>>> print http(r"""
... POST /test_folder_1_/ftf/unicodetest/@@edit.html HTTP/1.1
... Authorization: Basic manager:r00t
... Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
... Content-Type: multipart/form-data; boundary=---------------------------968064918930967154199105236
... Content-Length: 418
...
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.title"
...
... ChineseTitle
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.description"
...
... ChineseDescription
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somenumber"
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Change
... -----------------------------968064918930967154199105236--
... """ % ni_hao, handle_errors=False)
HTTP/1.1 200 OK
...
There are <strong>1</strong> input errors.
...
We see that the object hasn't changed:
>>> unicodetest.title == ni_hao.decode('utf-8')
True
>>> unicodetest.description == wo_hen_hao.decode('utf-8')
True
>>> unicodetest.somenumber
0
Now we provide some valid form data:
>>> print http(r"""
... POST /test_folder_1_/ftf/unicodetest/@@edit.html HTTP/1.1
... Authorization: Basic manager:r00t
... Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
... Content-Type: multipart/form-data; boundary=---------------------------968064918930967154199105236
... Content-Length: 418
...
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.title"
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.description"
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somenumber"
...
... 1
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Change
... -----------------------------968064918930967154199105236--
... """ % (wo_hen_hao, ni_hao), handle_errors=False)
HTTP/1.1 200 OK
...
We see that the object's data has changed:
>>> unicodetest.title == wo_hen_hao.decode('utf-8')
True
>>> unicodetest.description == ni_hao.decode('utf-8')
True
>>> unicodetest.somenumber
1
Let's also not forget about List widgets. Let's see if we can add an
element to the list:
>>> print http(r"""
... POST /test_folder_1_/ftf/unicodetest/@@edit.html HTTP/1.1
... Authorization: Basic manager:r00t
... Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
... Content-Type: multipart/form-data; boundary=---------------------------968064918930967154199105236
... Content-Length: 418
...
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.title"
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.description"
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somenumber"
...
... 1
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somelist.add"
...
... Add Some item
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somelist.count"
...
... 0
... -----------------------------968064918930967154199105236--
... """ % (wo_hen_hao, ni_hao), handle_errors=False)
HTTP/1.1 200 OK
...
...<input class="textType" id="field.somelist.0." name="field.somelist.0." size="20" type="text" value="" />...
...
Now, let's enter some more Chinese:
>>> de_guo = '\345\276\267\345\233\275'
>>> print http(r"""
... POST /test_folder_1_/ftf/unicodetest/@@edit.html HTTP/1.1
... Authorization: Basic manager:r00t
... Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
... Content-Type: multipart/form-data; boundary=---------------------------968064918930967154199105236
... Content-Length: 418
...
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.title"
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.description"
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somenumber"
...
... 1
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somelist.0."
...
... %s
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somelist.count"
...
... 1
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Change
... -----------------------------968064918930967154199105236--
... """ % (wo_hen_hao, ni_hao, de_guo), handle_errors=False)
HTTP/1.1 200 OK
...
The object's data will have changed accordingly:
>>> unicodetest.somelist == [de_guo.decode('utf-8')]
True
Object widget:
--------------
A little more complex is the ``ObjectWidget``. Here we simply test
that the edit form works:
>>> from Products.Five.form.tests.schemacontent import \
... manage_addComplexSchemaContent
>>> n = manage_addComplexSchemaContent(self.folder.ftf, 'objecttest')
>>> print http(r"""
... GET /test_folder_1_/ftf/objecttest/@@edit.html HTTP/1.1
... """, handle_errors=False)
HTTP/1.1 200 OK
...
Clean up
--------
Finally, we need to clean up:
>>> from zope.component.testing import tearDown
>>> tearDown()
src/Products/Five/form/tests/locales/de/LC_MESSAGES/formtest.mo
deleted
100644 → 0
View file @
140ff24e
File deleted
src/Products/Five/form/tests/locales/de/LC_MESSAGES/formtest.po
deleted
100644 → 0
View file @
140ff24e
##############################################################################
#
# Copyright (c) 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
msgid ""
msgstr ""
"Project-Id-Version: Five form tests\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2005-07-29 11:38+0100\n"
"Last-Translator: \n"
"Language-Team: Five Developers <z3-five@zope.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "Title"
msgstr "Titel"
msgid "A short description of the event."
msgstr "Eine kurze Beschreibung des Ereignisses."
msgid "Description"
msgstr "Beschreibung"
msgid "A long description of the event."
msgstr "Eine ausführliche Beschreibung des Ereignisses."
msgid "Some number"
msgstr "Irgendeine Zahl"
msgid "Some List"
msgstr "Irgendeine Liste"
msgid "Some item"
msgstr "Irgendeine Element"
msgid "Edit Field Content"
msgstr "Felderinhalt bearbeiten"
msgid "Add Field Content"
msgstr "Felderinhalt hinzufügen"
src/Products/Five/form/tests/locales/formtest.pot
deleted
100644 → 0
View file @
140ff24e
##############################################################################
#
# Copyright (c) 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
msgid ""
msgstr ""
"Project-Id-Version: Five form tests\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: Five Developers <z3-five@zope.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "Title"
msgstr ""
msgid "A short description of the event."
msgstr ""
msgid "Description"
msgstr ""
msgid "A long description of the event."
msgstr ""
msgid "Some number"
msgstr ""
msgid "Some List"
msgstr ""
msgid "Some item"
msgstr ""
msgid "Edit Field Content"
msgstr ""
msgid "Add Field Content"
msgstr ""
src/Products/Five/form/tests/schemacontent.py
deleted
100644 → 0
View file @
140ff24e
##############################################################################
#
# Copyright (c) 2004, 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Demo schema content
$Id$
"""
from
App.class_init
import
InitializeClass
from
OFS.SimpleItem
import
SimpleItem
from
Products.Five.form.objectwidget
import
ObjectWidget
from
zope.i18nmessageid
import
MessageFactory
from
zope.interface
import
implements
,
Interface
from
zope.schema
import
TextLine
,
Text
,
Object
,
Int
,
List
from
zope.app.form
import
CustomWidgetFactory
_
=
MessageFactory
(
'formtest'
)
class
IFieldContent
(
Interface
):
title
=
TextLine
(
title
=
_
(
u"Title"
),
description
=
_
(
u"A short description of the event."
),
default
=
u""
,
required
=
True
)
description
=
Text
(
title
=
_
(
u"Description"
),
description
=
_
(
u"A long description of the event."
),
default
=
u""
,
required
=
False
)
somenumber
=
Int
(
title
=
_
(
u"Some number"
),
default
=
0
,
required
=
False
)
somelist
=
List
(
title
=
_
(
u"Some List"
),
value_type
=
TextLine
(
title
=
_
(
u"Some item"
)),
default
=
[],
required
=
False
)
class
FieldContent
(
SimpleItem
):
"""A Viewable piece of content with fields"""
implements
(
IFieldContent
)
meta_type
=
'Five FieldContent'
def
__init__
(
self
,
id
,
title
):
self
.
id
=
id
self
.
title
=
title
InitializeClass
(
FieldContent
)
def
manage_addFieldContent
(
self
,
id
,
title
,
REQUEST
=
None
):
"""Add the field content"""
id
=
self
.
_setObject
(
id
,
FieldContent
(
id
,
title
))
return
''
class
IComplexSchemaContent
(
Interface
):
fishtype
=
TextLine
(
title
=
u"Fish type"
,
description
=
u"The type of fish"
,
default
=
u"It was a lovely little fish. And it went wherever I did go."
,
required
=
False
)
fish
=
Object
(
title
=
u"Fish"
,
schema
=
IFieldContent
,
description
=
u"The fishy object"
,
required
=
True
)
class
ComplexSchemaContent
(
SimpleItem
):
implements
(
IComplexSchemaContent
)
meta_type
=
"Five ComplexSchemaContent"
def
__init__
(
self
,
id
):
self
.
id
=
id
self
.
fish
=
FieldContent
(
'fish'
,
'title'
)
self
.
fish
.
description
=
""
self
.
fishtype
=
'Lost fishy'
class
ComplexSchemaView
:
"""Needs a docstring"""
fish_widget
=
CustomWidgetFactory
(
ObjectWidget
,
FieldContent
)
InitializeClass
(
ComplexSchemaContent
)
def
manage_addComplexSchemaContent
(
self
,
id
,
REQUEST
=
None
):
"""Add the complex schema content"""
id
=
self
.
_setObject
(
id
,
ComplexSchemaContent
(
id
))
return
''
def
modifiedSubscriber
(
content
,
ev
):
"""A simple event handler, which sets a flag on the object"""
content
.
_modified_flag
=
True
def
createdSubscriber
(
content
,
ev
):
"""A simple event handler, which sets a flag on the object"""
content
.
_created_flag
=
True
src/Products/Five/form/tests/test_forms.py
deleted
100644 → 0
View file @
140ff24e
##############################################################################
#
# Copyright (c) 2004, 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Test forms
$Id$
"""
def
test_get_widgets_for_schema_fields
():
"""
Test widget lookup for schema fields
First, load the configuration files:
>>> import Products.Five
>>> from Products.Five import zcml
>>> zcml.load_config('configure.zcml', Products.Five)
Now for some actual testing...
>>> from zope.schema import Choice, TextLine
>>> salutation = Choice(title=u'Salutation',
... values=("Mr.", "Mrs.", "Captain", "Don"))
>>> contactname = TextLine(title=u'Name')
>>> from zope.publisher.browser import TestRequest
>>> request = TestRequest()
>>> salutation = salutation.bind(request)
>>> contactname = contactname.bind(request)
>>> from zope.component import getMultiAdapter
>>> from zope.app.form.interfaces import IInputWidget
>>> from zope.app.form.browser.textwidgets import TextWidget
>>> from zope.app.form.browser.itemswidgets import DropdownWidget
>>> view1 = getMultiAdapter((contactname, request), IInputWidget)
>>> view1.__class__ == TextWidget
True
>>> view2 = getMultiAdapter((salutation, request), IInputWidget)
>>> view2.__class__ == DropdownWidget
True
Clean up:
>>> from zope.component.testing import tearDown
>>> tearDown()
"""
def
test_suite
():
import
unittest
from
zope.testing.doctest
import
DocTestSuite
from
Testing.ZopeTestCase
import
FunctionalDocFileSuite
return
unittest
.
TestSuite
((
DocTestSuite
(),
FunctionalDocFileSuite
(
'forms.txt'
,
package
=
"Products.Five.form.tests"
,),
))
src/Products/Five/formlib/__init__.py
View file @
31d4a7c2
# package
# BBB
\ No newline at end of file
\ No newline at end of file
src/Products/Five/formlib/configure.zcml
View file @
31d4a7c2
<configure
<configure xmlns="http://namespaces.zope.org/zope">
package="zope.formlib"
xmlns="http://namespaces.zope.org/zope"
i18n_domain="zope">
<adapter
<include package="five.formlib" />
factory=".form.render_submit_button"
name="render"
/>
<!-- Error view for 'Invalid' -->
<adapter
for="zope.interface.Invalid
zope.publisher.interfaces.browser.IBrowserRequest"
factory=".errors.InvalidErrorView"
permission="zope.Public"
/>
</configure>
</configure>
src/Products/Five/formlib/formbase.py
View file @
31d4a7c2
##############################################################################
# BBB
#
from
five.formlib.formbase
import
FiveFormlibMixin
# Copyright (c) 2006 Zope Corporation and Contributors.
from
five.formlib.formbase
import
FormBase
# All Rights Reserved.
from
five.formlib.formbase
import
EditFormBase
#
from
five.formlib.formbase
import
DisplayFormBase
# This software is subject to the provisions of the Zope Public License,
from
five.formlib.formbase
import
AddFormBase
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
from
five.formlib.formbase
import
PageForm
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
from
five.formlib.formbase
import
Form
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
from
five.formlib.formbase
import
PageEditForm
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
from
five.formlib.formbase
import
EditForm
# FOR A PARTICULAR PURPOSE.
from
five.formlib.formbase
import
PageDisplayForm
#
from
five.formlib.formbase
import
DisplayForm
##############################################################################
from
five.formlib.formbase
import
PageAddForm
"""Five baseclasses for zope.formlib.form
from
five.formlib.formbase
import
AddForm
from
five.formlib.formbase
import
SubPageForm
$Id$
from
five.formlib.formbase
import
SubPageEditForm
"""
from
five.formlib.formbase
import
SubPageDisplayForm
import
os.path
import
zope.event
import
zope.formlib
import
zope.lifecycleevent
from
zope
import
interface
from
zope.formlib
import
interfaces
,
form
from
zope.i18nmessageid
import
MessageFactory
_
=
MessageFactory
(
"zope"
)
from
Products.Five.browser.pagetemplatefile
import
ViewPageTemplateFile
from
Products.Five.browser.decode
import
processInputs
,
setPageEncoding
_FORMLIB_DIR
=
os
.
path
.
dirname
(
zope
.
formlib
.
__file__
)
_PAGEFORM_PATH
=
os
.
path
.
join
(
_FORMLIB_DIR
,
'pageform.pt'
)
_SUBPAGEFORM_PATH
=
os
.
path
.
join
(
_FORMLIB_DIR
,
'subpageform.pt'
)
class
FiveFormlibMixin
(
object
):
# Overrides the formlib.form.FormBase.template attributes implemented
# using NamedTemplates. NamedTemplates using ViewPageTemplateFile (like
# formlib does by default) cannot work in Zope2.
# XXX Maybe we need to have Five-compatible NamedTemplates?
template
=
ViewPageTemplateFile
(
_PAGEFORM_PATH
)
# Overrides formlib.form.FormBase.update. Make sure user input is
# decoded first and the page encoding is set before proceeding.
def
update
(
self
):
processInputs
(
self
.
request
)
setPageEncoding
(
self
.
request
)
super
(
FiveFormlibMixin
,
self
).
update
()
class
FormBase
(
FiveFormlibMixin
,
form
.
FormBase
):
pass
class
EditFormBase
(
FiveFormlibMixin
,
form
.
EditFormBase
):
pass
class
DisplayFormBase
(
FiveFormlibMixin
,
form
.
DisplayFormBase
):
pass
class
AddFormBase
(
FiveFormlibMixin
,
form
.
AddFormBase
):
pass
class
PageForm
(
FormBase
):
interface
.
implements
(
interfaces
.
IPageForm
)
Form
=
PageForm
class
PageEditForm
(
EditFormBase
):
interface
.
implements
(
interfaces
.
IPageForm
)
EditForm
=
PageEditForm
class
PageDisplayForm
(
DisplayFormBase
):
interface
.
implements
(
interfaces
.
IPageForm
)
DisplayForm
=
PageDisplayForm
class
PageAddForm
(
AddFormBase
):
interface
.
implements
(
interfaces
.
IPageForm
)
AddForm
=
PageAddForm
class
SubPageForm
(
FormBase
):
template
=
ViewPageTemplateFile
(
_SUBPAGEFORM_PATH
)
interface
.
implements
(
interfaces
.
ISubPageForm
)
class
SubPageEditForm
(
EditFormBase
):
template
=
ViewPageTemplateFile
(
_SUBPAGEFORM_PATH
)
interface
.
implements
(
interfaces
.
ISubPageForm
)
class
SubPageDisplayForm
(
DisplayFormBase
):
template
=
ViewPageTemplateFile
(
_SUBPAGEFORM_PATH
)
interface
.
implements
(
interfaces
.
ISubPageForm
)
src/Products/Five/formlib/tests/__init__.py
deleted
100644 → 0
View file @
140ff24e
# package
\ No newline at end of file
src/Products/Five/formlib/tests/configure.zcml
deleted
100644 → 0
View file @
140ff24e
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:meta="http://namespaces.zope.org/meta"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:five="http://namespaces.zope.org/five"
xmlns:i18n="http://namespaces.zope.org/i18n"
i18n_domain="formtest"
>
<browser:page
name="add_content"
for="*"
class=".view.AddContentForm"
permission="zope2.Public"
/>
<browser:page
name="edit_content"
for=".content.IContent"
class=".view.EditContentForm"
permission="zope2.Public"
/>
</configure>
src/Products/Five/formlib/tests/content.py
deleted
100644 → 0
View file @
140ff24e
##############################################################################
#
# Copyright (c) 2004, 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Test content.
$Id$
"""
from
App.class_init
import
InitializeClass
from
OFS.SimpleItem
import
SimpleItem
from
zope.i18nmessageid
import
MessageFactory
from
zope.interface
import
implements
from
zope.interface
import
Interface
from
zope.schema
import
ASCIILine
from
zope.schema
import
List
from
zope.schema
import
TextLine
_
=
MessageFactory
(
'formtest'
)
class
IContent
(
Interface
):
id
=
ASCIILine
(
title
=
_
(
u"Id"
),
description
=
_
(
u"The object id."
),
default
=
''
,
required
=
True
)
title
=
TextLine
(
title
=
_
(
u"Title"
),
description
=
_
(
u"A short description of the event."
),
default
=
u""
,
required
=
True
)
somelist
=
List
(
title
=
_
(
u"Some List"
),
value_type
=
TextLine
(
title
=
_
(
u"Some item"
)),
default
=
[],
required
=
False
)
class
Content
(
SimpleItem
):
"""A Viewable piece of content with fields
"""
implements
(
IContent
)
meta_type
=
'Five Formlib Test Content'
def
__init__
(
self
,
id
,
title
,
somelist
=
None
):
self
.
id
=
id
self
.
title
=
title
self
.
somelist
=
somelist
InitializeClass
(
Content
)
src/Products/Five/formlib/tests/formlib.txt
deleted
100644 → 0
View file @
140ff24e
Testing formlib integration
===========================
This doctest is will test the Five formlib support and to provide some
examples.
It will not test the actual formlib functionality. See
zope/formlib/form.txt for tests and more explanations of zope.formlib
Before we can begin, we need to set up a few things. We need a manager
account:
>>> uf = self.folder.acl_users
>>> uf._doAddUser('manager', 'r00t', ['Manager'], [])
We need to configure all of Five and the necessary formlib components for
this test:
>>> from Products.Five import zcml
>>> import Products.Five
>>> zcml.load_config('meta.zcml', Products.Five)
>>> import Products.Five.form.tests
>>> zcml.load_config('configure.zcml', package=Products.Five)
>>> zcml.load_config('configure.zcml', package=Products.Five.formlib.tests)
Finally, we need to setup a traversable folder. Otherwise, Five won't get
to to do its view lookup:
>>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
>>> manage_addFiveTraversableFolder(self.folder, 'ftf')
Let's set up a testbrowser:
>>> from Products.Five.testbrowser import Browser
>>> browser = Browser()
>>> browser.addHeader('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7')
>>> browser.addHeader('Accept-Language', 'en-US')
>>> browser.addHeader('Authorization', 'Basic manager:r00t')
Let's 'manually' create a Content instance and add it to the folder:
>>> from Products.Five.formlib.tests import content
>>> folder = self.folder.ftf
>>> obj = content.Content('content_1', 'Title', [])
>>> folder._setObject('content_1', obj)
'content_1'
>>> print folder.content_1.title
Title
Now we can edit this content object, e.g. changing the title. Formlib,
like the traditional AddView and EditView, supports unicode:
>>> browser.open("http://localhost/test_folder_1_/ftf/content_1/@@edit_content")
>>> ni_hao = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> ctl = browser.getControl(name="form.title")
>>> ctl.value = ni_hao
>>> browser.getControl(name="form.actions.apply").click()
>>> isinstance(folder.content_1.title, unicode)
True
>>> folder.content_1.title == ni_hao.decode('utf-8')
True
Adding a new content object, with two list items:
>>> browser.open("http://localhost/test_folder_1_/ftf/@@add_content")
>>> ctl = browser.getControl(name="form.id")
>>> ctl.value = 'test123'
>>> ctl = browser.getControl(name="form.title")
>>> ctl.value = ni_hao
>>> browser.getControl(name="form.somelist.add").click()
>>> ctl = browser.getControl(name="form.somelist.0.")
>>> ctl.value = 'a nice list item'
>>> browser.getControl(name="form.somelist.add").click()
>>> ctl = browser.getControl(name="form.somelist.1.")
>>> ctl.value = 'a nice list item'
>>> browser.getControl(name="form.actions.add").click()
>>> print folder.test123.somelist
[u'a nice list item', u'a nice list item']
Clean up
--------
Finally, we need to clean up:
>>> from zope.component.testing import tearDown
>>> tearDown()
src/Products/Five/formlib/tests/test_formlib.py
deleted
100644 → 0
View file @
140ff24e
##############################################################################
#
# Copyright (c) 2006 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Test forms
$Id$
"""
def
test_suite
():
import
unittest
from
Testing.ZopeTestCase
import
FunctionalDocFileSuite
return
unittest
.
TestSuite
((
FunctionalDocFileSuite
(
'formlib.txt'
,
package
=
'Products.Five.formlib.tests'
),
))
src/Products/Five/formlib/tests/view.py
deleted
100644 → 0
View file @
140ff24e
##############################################################################
#
# Copyright (c) 2006 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Five baseclasses for zope.formlib.form
$Id$
"""
from
zope.formlib
import
form
from
Products.Five.formlib.formbase
import
AddForm
,
EditForm
from
Products.Five.formlib.tests.content
import
IContent
,
Content
class
AddContentForm
(
AddForm
):
"""AddForm for creating and adding IContent objects
"""
form_fields
=
form
.
Fields
(
IContent
)
def
createAndAdd
(
self
,
data
):
id
=
data
.
get
(
'id'
)
ctnt
=
Content
(
id
,
data
.
get
(
'title'
),
somelist
=
data
.
get
(
'somelist'
))
self
.
context
.
_setObject
(
id
,
ctnt
)
class
EditContentForm
(
EditForm
):
"""EditForm for editing IContent objects
"""
form_fields
=
form
.
Fields
(
IContent
)
versions.cfg
View file @
31d4a7c2
...
@@ -7,6 +7,7 @@ ClientForm = 0.2.10
...
@@ -7,6 +7,7 @@ ClientForm = 0.2.10
DateTime = 2.12.0
DateTime = 2.12.0
docutils = 0.6
docutils = 0.6
ExtensionClass = 2.11.3
ExtensionClass = 2.11.3
five.formlib = 1.0.2
lxml = 2.2
lxml = 2.2
mechanize = 0.1.11
mechanize = 0.1.11
Persistence = 2.11.1
Persistence = 2.11.1
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment