Form
Dexterity 使用 z3c.form 函式庫,zope.formlib 使用 plone.app.form 函式庫。在 schema driven 場合,常使用 z3c.form 來顯示 widget,可留意 collective.z3cform.widgets 或 plone.formwidget.contenttree 的發展。
z3c.form
z3c.form 繼承自 BrowserPage,在 Plone 3 引進,在 Plone 4 廣泛應用。基本的 Base Class 包括 z3c.form.form.BaseForm 用於 Page Form, Edit Form, Add Form, Display Form 等,也被 plone.directives 繼承與延伸。建立簡易 Widget 的範例
<browser:page for="*" name="myform" template="myform.pt" permission="zope.Public" />
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" metal:use-macro="context/main_template/macros/master">
<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" /> </form>
加進的 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>
<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> </div> </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 --> </div> <ul class="visualNoMarker" id="ref_browser_items_referenze" > </ul> <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&fieldRealName=relatedItems&at_url=${at_url}&" /> <input type="submit" name="send" value="Invia" /> </form>
<head> <metal:head fill-slot="javascript_head_slot"> <script type="text/javascript" src="" tal:attributes="src string:${portal_url}/referencebrowser.js"></script> </metal:head> </head>
radio_input.pt bug multi select widget bug in Plone 4.3.6
ftw.datepicker example example by beetlebrow
# browser/alertforms.py 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 z3c.form.browser.radio 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( vocabulary=deal_types, title=_(u'label_tour_op_deals', default=u'Tour operator deals'), description=_(u'help_tour_op_deals', default=u"Tour operator deal info " "..."), required=True, ) other_deals = schema.Choice( vocabulary=deal_types, title=_(u'other_deals', default=u'Other supplier deals'), description=_(u'help_other_deals', default=u"e.g. Lift passes etc. " "..."), required=True, ) country = schema.TextLine( title=_(u'label_country', default=u'Country'), description=_(u'help_country', default=u"Leave blank for any."), required=False) resort = schema.TextLine( title=_(u'label_resort', default=u'Resort'), description=_(u'help_resort', default=u"Leave blank for any."), required=False) flexible = schema.Bool(title=_(u'label_flexible', default=u'I am flexible'), required=False, default=False) who = schema.Choice( vocabulary=who_is_going, title=_(u'label_who', default=u'Who is going?'), required=True) adults_no = schema.Int( title=_(u'label_adultsno', default=u'No. of adults'), required=True) children_no = schema.Int( title=_(u'label_childno', default=u'No. of children under 11'), required=False) departuredate = schema.Date( title=_(u'label_departuredate', default=u'When would you like to go on holiday?'), description=_(u'help_departuredate', default=u"Departure date +/- 2days. Leave blank if flexible."), required=False) alertsfrom = schema.Date( title=_(u'label_alertsfrom', default=u'When would you like to start receiving alerts?'), description=_(u'help_alertsfrom', default=u"Leave blank for as soon as possible."), required=False) # 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 dealalertform.pt in alertforms_templates/ would do it # but only 'template = ...' seemed to work template = ViewPageTemplateFile('templates/dealalertform.pt') # 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: return # 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 logger.info('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="http://www.w3.org/1999/xhtml" xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:i18n="http://xml.zope.org/namespaces/i18n" i18n:domain="example.dexterityforms" metal:use-macro="context/main_template/macros/master"> <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. </tal:x> <div id="content-core"> <metal:block use-macro="context/@@ploneform-macros/titlelessform" /> </div> <tal:x replace="nothing"> Couldn't get the /field macro to work. Used various values for widget?? </tal:x> <div tal:define="widget string:formfield-form-widgets-tour_deals"> <metal:block use-macro="context/@@ploneform-macros/field" /> </div> <tal:x replace="nothing" />
<tal:field tal:replace="structure view/widgets/tour_deals/@@ploneform-render-widget" /> </metal:block> </html>
<browser:page for="*" name="deal-alerts" class=".alertforms.DealAlertView" layer=".interfaces.IThemeSpecific" permission="zope2.View" />
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 collective.contact.contactlist
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, navigation_tree_query=navigation_tree_query) del self.navigation_tree_query['portal_type'] self.navigation_tree_query['path']['query'] = \ '/'.join(context.getPhysicalPath()) 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 plone.app.event
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:
- Leave the form as is, and set the field's mode directly. That is, add this on line 128:
fields['leaveblank'].mode = 'hidden' - 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'), required=False, ) form.mode(leaveblank='hidden') added to interface: validator.WidgetValidatorDiscriminators(NorobotsValidator, field=ITemplateaccountForm2['norobots']) grok.global_adapter(NorobotsValidator)
ContactForm: AutoExtensibleForm Example 說明文件
mockup 讓 z3cform ARIA support 變得沒必要
formlib to z3c.form: eea.annotator
plone.directives.form
搭配 grokcore.* 來建立表單,啟用方式是在 meta.zcml 和 configure.zcml 裡使用下列設定:
<include package="plone.directives.form" file="meta.zcml" /> <include package="plone.directives.form" />
另一種方式,是在 setup.py 裡指定 install_requires 的話,可使用下列設定:
<includeDependencies package="." />
collective.easyform
類似 PloneFormGen 的方案,適用於 Dexterity 型別,支援 Action 與 Test 工作。
plone.souper
zope.formlib
未來不建議使用 移除範例: 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
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' else: 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
http://learnplone.org/documentation/tutorial/ploneformgen-recipies
DateTime like Field by Custom CSS
Checking Submit Condition Confirm Data Before Submit
欄位模式可以指定為 display,這樣就會取消輸入介面:
from plone.directives import form form.mode(title_declaration_legal='display')
YAFOWIL: Yet Another FOrm WIdget Library
import datetime from collective.z3cform.datetimewidget.widget import DateWidget from plone.z3cform import z2 def when_widget(self): z2.switch_on(self) widget = DateWidget(self.request) widget.name = 'when' widget.ignoreContext = True widget.update() 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 的相依關係。
z3c.ptcompat instead of z3c.form.ptcompat