Skip to content. | Skip to navigation

Personal tools


You are here: Home / Tips / Form


透過網頁選單或是檔案系統的程式碼,可以建立獨立執行的表單,常見的工具包括 PloneFormGen EasyForm 或是 z3c.form 函式庫等。

Dexterity 使用 z3c.form 函式庫,zope.formlib 使用 函式庫。在 schema driven 場合,常使用 z3c.form顯示 widget,可留意 collective.z3cform.widgetsplone.formwidget.contenttree 的發展。


z3c.form 繼承自 BrowserPage在 Plone 3 引進,在 Plone 4 廣泛應用。基本的 Base Class 包括 z3c.form.form.BaseForm 用於 Page Form, Edit Form, Add Form, Display Form 等,也被 plone.directives 繼承與延伸。建立簡易 Widget 的範例

  permission="zope.Public" />
<html xmlns="" xml:lang="en"

<body> <metal:content-core fill-slot="content-core"> <metal:content-core define-macro="content-core"> <form action="@@gestisciform" method="post"> <input type="text" name="name" value="Nome" /> <input type="submit" name="send" value="Invia" /> </form> </metal:content-core> </metal:content-core> </body> </html>
<form action="@@gestisciform" method="post">

  <textarea name="testo"></textarea>
  <input type="submit" name="send" value="Invia" />


加進的 pat-tinymce 和 mce_editable 會被 TinyMCE 和 jQuery 所套用

<textarea name="testo" class="pat-tinymce mce_editable"></textarea>

再加 data-mce-config 設定值,這會被 TinyMCE 註冊的 View 所套用

<form action="@@gestisciform" method="post">

  <textarea name="testo" class="pat-tinymce mce_editable"
   tal:define="configuration_method nocall:here/@@tinymce-jsonconfiguration;
               configuration_json python:configuration_method(field=None);"
   tal:attributes="data-mce-config configuration_json"></textarea>
  <input type="submit" name="send" value="Invia" />

<form action="@@gestisciform" method="post">

    <div id="atrb_referenze" class="overlay-ajax overlay">
        <div class="close"><span>Chiudi</span></div>
        <div class="pb-ajax">
            <div class="overlaycontent" style="font-size: 125%"></div>

    <input type="hidden" name="referenze:default:list" value="" />
    <input type="hidden" value="1" name="referenze-sortable" />

    <div style="float: left"> <!-- don't remove this. it is needed for DOM traversal -->
    <ul class="visualNoMarker" id="ref_browser_items_referenze" >

    <input type="button" rel="#atrb_referenze" src=""
           class="addreference searchButton" value="Aggiungi..."
           tal:define="startup_directory context/absolute_url;
                       helper python:context.restrictedTraverse('refbrowserhelper', nothing);
                       at_url helper/getAtURL|nothing;"
       tal:attributes="src string:${startup_directory}/refbrowser_popup?fieldName=referenze&amp;fieldRealName=relatedItems&amp;at_url=${at_url}&amp;" />

    <input type="submit" name="send" value="Invia" />


<metal:head fill-slot="javascript_head_slot">
<script type="text/javascript" src=""
 tal:attributes="src string:${portal_url}/referencebrowser.js"></script>

</head> bug multi select widget bug in Plone 4.3.6

ftw.datepicker example example by beetlebrow

# browser/
from Products.CMFPlone import PloneMessageFactory as _
from zope.interface import Interface
from zope import schema
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
from z3c.form import form, field, button
from plone.z3cform.layout import wrap_form
from import RadioFieldWidget
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile

import logging
logger = logging.getLogger("alert form")

# define vocabularies for singleselection fields

deal_types = SimpleVocabulary(
    [SimpleTerm(value=u'E', title=_(u'Early booking deals')),
     SimpleTerm(value=u'L', title=_(u'Last minute deals')),
     SimpleTerm(value=u'S', title=_(u'All season deals')),
     SimpleTerm(value=u'A', title=_(u'All deals'))]
who_is_going = SimpleVocabulary(
    [SimpleTerm(value=u'F', title=_(u'Family - require childcare and/or kids programmes')),
     SimpleTerm(value=u'A', title=_(u'Adults - no childcare or kids programmes necessary'))]

# the fields to be displayed

class IDealAlert(Interface):
    tour_deals = schema.Choice(
        title=_(u'label_tour_op_deals', default=u'Tour operator deals'),
                      default=u"Tour operator deal info "
    other_deals = schema.Choice(
        title=_(u'other_deals', default=u'Other supplier deals'),
                      default=u"e.g. Lift passes etc. "
    country = schema.TextLine(
        title=_(u'label_country', default=u'Country'),
        description=_(u'help_country', default=u"Leave blank for any."),
    resort = schema.TextLine(
        title=_(u'label_resort', default=u'Resort'),
        description=_(u'help_resort', default=u"Leave blank for any."),
    flexible = schema.Bool(title=_(u'label_flexible', 
        default=u'I am flexible'),
    who = schema.Choice(
        title=_(u'label_who', default=u'Who is going?'),
    adults_no = schema.Int(
        title=_(u'label_adultsno', default=u'No. of adults'),
    children_no = schema.Int(
        title=_(u'label_childno', default=u'No. of children under 11'),
    departuredate = schema.Date(
        title=_(u'label_departuredate', default=u'When would you like to go on holiday?'),
                      default=u"Departure date +/- 2days. Leave blank if flexible."),        
    alertsfrom = schema.Date(
        title=_(u'label_alertsfrom', default=u'When would you like to start receiving alerts?'),
                      default=u"Leave blank for as soon as possible."),

# the form view 
# override the drop-downs with radiobutton widgets.
# some docs used updateFields() method for this but...

class DealAlertForm(form.Form):
    fields = field.Fields(IDealAlert)
    fields['tour_deals'].widgetFactory = RadioFieldWidget
    fields['other_deals'].widgetFactory = RadioFieldWidget
    fields['who'].widgetFactory = RadioFieldWidget
    ignoreContext = True     # don't use context to get widget data
    label = _(u"Send a deal alert")
    description = _(u"You don't miss out on a great deal by being too specific on the requirements.")

# the form will be generated automatically but I wanted more control
# for styling so a defined a template
# some docs used 'index =...' and also hinted that auto placement
# of a in alertforms_templates/ would do it 
# but only 'template = ...' seemed to work

    template = ViewPageTemplateFile('templates/')

# some minor widget adjustment

    def updateWidgets(self):
        super(DealAlertForm, self).updateWidgets()
        # Widgets
        self.widgets['adults_no'].size = 2
        self.widgets['children_no'].size = 2

# the submit buitton handler    
    @button.buttonAndHandler(u'Send deals')
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:

# form data - do what you need to with it 
# ie it will be emailed...

#        if data.has_key('text'):
#            print data['text'] # ... or do stuff   'handleApply form data:%s', data)

# if you want form wrapped in a new page        
#DealAlertView = wrap_form(DealAlertForm)
# but I'm using a template so I don't
DealAlertView = DealAlertForm
<html xmlns=""

<metal:block fill-slot="main">
<h1 class="documentFirstHeading" tal:content="view/label | nothing" />
<p>Welcome to this form.</p>
<tal:x replace="nothing">
this diplays the whole form if the customisation is minimal.
<div id="content-core">
  <metal:block use-macro="context/@@ploneform-macros/titlelessform" />

<tal:x replace="nothing">
 Couldn't get the /field macro to work. Used various values for widget??
        <div tal:define="widget string:formfield-form-widgets-tour_deals">
           <metal:block use-macro="context/@@ploneform-macros/field" />

<tal:x replace="nothing" />
<tal:field tal:replace="structure view/widgets/tour_deals/@@ploneform-render-widget" />
      permission="zope2.View" />

預設值可能無法設定為 None 或 ''

garbas 教學手冊 collective.examples.userdata: FormExtender change the widget outside the class level

plone.autoform 可以依據 Model (Schema) 的定義,來建置 z3c.form 表單,定義的內容包括 Field、Widget、Option 等,可設定的內容包括 Order 等。

collective.z3cform.chosen Override Button Action Handler Widget for Dict Field Plone 4.3.7 之後要 import zope.browserpage as Z3ViewPageTemplateFile

Plone Core hates Grok without grok 從 z3c.form 2.6.0 版本起,Radio Button 不再有 :list,以 z3c.formwidget.query 為例,要配合昇級。

Rendering z3cform Wizard as Standalone View: override with template that calls the ploneform-macros

Creating New ContentTreeWidget for z3cform: override the widget for relateditems collective.z3cform.html5widgets

Add Custom CSS File Without Using Custom Template TinyMCE HTML form embedded

Custom Object Source Binder

from plone.formwidget.contenttree.source import ObjPathSource
from plone.formwidget.contenttree.source import ObjPathSourceBinder

class SubTreeObjPathSource(ObjPathSource):
    def __init__(self, context, selectable_filter, navigation_tree_query=None):
        super(SubTreeObjSource, self).__init__(
            context, selectable_filter,
        del self.navigation_tree_query['portal_type']
        self.navigation_tree_query['path']['query'] = \

class SubTreeObjPathSourceBinder(ObjPathSourceBinder):
    path_source = SubTreeObjPathSource
contact_person = RelationList(
    title = _(u"Contact Person"),
    value_type = RelationChoice(
        source = SubTreeObjPathSourceBinder()

利用 requests 執行 GET POST 表單內容 CheckBoxFieldWidget Dynamic Vocabulary

collective.z3cform.widgets JS compact with jQuery 1.9 and render CSS resources as <link />

z3c.formwidget.query: radio checkbox property is a generator

z3cform portlet support: collective.portlet.ngcollection

Schema 的載入語法寫成 from plone.directives import form 導致用 plone.directives.form 找不到需要改的字串線索

Hidden Form Field: Form hints in the schema are ignored if your form is a subclass of plone.directives.form.Form and specifies fields using fields = field.Fields, as you do here. They only take effect if your form subclasses plone.directives.form.SchemaForm (or some other subclass of plone.autoform.form.AutoExtensibleForm). You have a couple options:

  1. Leave the form as is, and set the field's mode directly. That is, add this on line 128:
    fields['leaveblank'].mode = 'hidden'
  2. Make the form extend SchemaForm instead of Form. Replace line 126 with "schema = ITemplateaccountForm2". Specify the widget for the norobots field with a hint in the schema rather than directly.
leaveblank = schema.ASCIILine(
    title=_(u'Please leave empty'),


added to interface:

ContactForm: AutoExtensibleForm Example 說明文件

mockup 讓 z3cform ARIA support 變得沒必要

formlib to z3c.form: eea.annotator


搭配 grokcore.* 來建立表單,啟用方式是在 meta.zcml 和 configure.zcml 裡使用下列設定:

<include package="plone.directives.form" file="meta.zcml" />
<include package="plone.directives.form" />

另一種方式,是在 裡指定 install_requires 的話,可使用下列設定:

<includeDependencies package="." />


類似 PloneFormGen 的方案,適用於 Dexterity 型別,支援 Action 與 Test 工作。


Store Form Inputs




未來不建議使用 移除範例: Products.GenericSetup

Plone Form Generator

PloneFormGen 適於簡易功能的表單場合,透過網頁選單就能自行產生 Archetypes 表單,包括 Field Widget Validator Action 的設定。架構上 PloneFormGen 是以目錄來當作表單元件的容器,每個欄位是目錄裡的內容型別,輸入到欄位的值能被顯示或檢驗,表單內容完整送出後,可以搭配 Action 來執行對應的處理工作。

FormStack: hosted service to collect your data and embed on your site

Pass Data from External Site

PloneFormGen Custom sc.pfg.brazilianfields Products.BrFieldsAndWidgets


python:[user.getProperty('email') for user in object.portal_groups.getGroupById('YOURGROUPID').getGroupMembers()]

TypeError: index_html() got an unexpected keyword argument 'charset' -- set "is as images" in the options so is not treated as a binary file

Disable Radio Button When Condition Met

Extending PloneFormGen sing dancing



request = container.REQUEST

if request.form['e-mail-address'] != request.form['confirm-e-mail-address']:
    return 'Your email address does not match'
    return False

# Place the script in the Custom Validate field of one or both of the fields:
# python: folder.confirmEmailAddress()

Products.validation: Validate Archetypes Field

DateTime like Field by Custom CSS

Checking Submit Condition Confirm Data Before Submit


Header Injection Example

欄位模式可以指定為 display,這樣就會取消輸入介面:

from plone.directives import form

YAFOWIL: Yet Another FOrm WIdget Library

import datetime
from collective.z3cform.datetimewidget.widget import DateWidget
from plone.z3cform import z2

def when_widget(self):
     widget = DateWidget(self.request) = 'when'
     widget.ignoreContext = True
     return widget.render()
<span tal:replace="structure view/when_widget" />

contact-info.cpt 修改經驗 contact-info encode reply-to address Report a Problem 上傳並顯示圖檔

Spam, Robot: collective.z3cform.norobots

和 Dexterity 進行比較: 網頁式管理介面較完整,例如 Products.ATVocabularyManager Products.PFGDataGrid 模組。

Removing Dependency

Products.CMFEditions: CMFControllerForms to BrowserView FormSchemaGrokker 從原本的 plone.directives.form 移到 plone.autoform,試圖移除 five.grok 的相依關係

z3cform contenttreewidget

z3c.form validation

z3c.ptcompat instead of z3c.form.ptcompat

JavaScript or Others

Adlib API collective.adlibsyncmanager

Job Application Materials Dropbox