Skip to content. | Skip to navigation

Personal tools

Navigation

You are here: Home / Tips / Fields and Widgets

Fields and Widgets

Fieldset https://github.com/plone/plone.formwidget.hcaptcha/issues/4 https://github.com/plone/plone.formwidget.hcaptcha/pull/5 Adding the adapter to supermodel.py allows adding the field [plone/plone.formwidget.hcaptcha] EasyForm requires field to provide IFromUnicode (Issue #4)

Multi-Select from Long List

Hiding Hidden Field Garbas z3c.form Tutorial for Field and Widget Using Widgets in Simple HTML Templates

使用 z3c.form 時要加上 <include package="plone.app.z3c.form" />

Custom Field WIdget Example

Fieldset

snippet from Form Scheme Hints

from plone.supermodel import model

class ISampleSchema(model.Schema):
    fieldset('extra',
        label=u'Extra Info',
        fields=['footer', 'dummy']
    )

TextField from text/plain to text/html

# Add a New Item

 z3c.form-3.2.11-py2.7.egg/z3c/form/widget.py(131)update()
-> if value not in (interfaces.NO_VALUE, PLACEHOLDER):
(Pdb) value
<NO_VALUE>
(Pdb) dir()
['adapter', 'default_value', 'field', 'lookForDefault', 'pdb', 'self', 'value']
(Pdb) self
<TextWidget 'form.widgets.title'>
(Pdb) field
<zope.schema._bootstrapfields.TextLine object at 0x7f081cf6afd0>

TextLine 如果沒有填值,並不會建立對應的變數,RichText 不管是否有填值,都會建立對應的變數,沒填值的會成為 None,Tuple 沒填值的會使用 missing_value=() 之類的預設值。

Default Value Tip and Example: select widget collective.nitf

field list

數值欄位支援增減按鈕 <input type="number" name="quantity" min="1" max="5">

zope.schema 可選用的基本欄位定義在 _field.py 的 classImplements() 裡,像用了 Tuple 或 List 會出現 ComponentLookupError: ((<zope.schema._field.Tuple object at 0xb1c8e94c> 錯誤的話,可檢查是否指定 value_type 參數值。

TBA

指定 ListSet 預設值的範例。

<field name="audience" type="zope.schema.Set">
<title>Audience</title>
<value_type type="zope.schema.Choice">
<values>
  <element>Beginner</element>
  <element>Advanced</element>
  <element>Professional</element>
</values>
</value_type>
</field>

Link Widget: Content Browser

https://github.com/collective/Products.Poi/pull/23 Products.Poi 更新 Widget 範例 plone.app.dexterity/behaviors/metadata.py subjects Field (指定 required=True 的話可能導致 Module z3c.form.widget, line 132, in update Module z3c.form.converter, line 337, in toWidgetValue TypeError: 'NoneType' object is not iterable ):

-    widget(subject=TextLinesFieldWidget)
-    subject = schema.List(
+    widget('subject',
+           AjaxSelectFieldWidget,
+           vocabulary='plone.app.vocabularies.Keywords')
+    subject = schema.Tuple(
         title=_(u'Subject'),
         description=_(u"Tags can be used to add arbitrary categorisation to "
                       u"issues. The list below shows existing tags which "

collective.z3cform.widgets 可能要搭配舊版 plone.app.jquerytools,有人降級到 1.6.2 還是無效,指定 collective.z3cform.widgets 為 1.0b11 有成功。技術解法之一是執行 document.ready 的 Event Handler 來處理:

var removeDraggableDoBody = function() {
    // Abort if draggable behavior does not exists.
    if (!$.fn.draggable) {
        return;
    }

    var $body = $('body');

    function removeDraggableFromBody() {
        if ($body.hasClass('ui-draggable')) {
            $body.draggable('destroy');
        }
    }

    // Tries to remove behavior if already active.
    removeDraggableFromBody();

    // Wait for behavior activation and immediately disables it.
    $body.on('dragcreate', function(event, ui) {
        removeDraggableFromBody();
    });
};

plone.formwidget.recurrence 客製化範例: z3cform/interfaces.py IText, IWidget

plone.app.z3cform 版本在 Plone 4.3 vs 5.0 差距很大,可觀察 RichTextWidget 的改進變化,在 widget.py 1.0.x branch 只有 DateWidget DateteimeWidget,在 2.0.x branch 則新增 SelectWidget AjaxSelectWidget RelatedItemsWidget QueryStringWidget RichTextWidget LinkWidget SingleCheckBoxBoolWidget。

# multiple-input: value1;value2
my_data = schema.TextLine(
    title=_(u"My Data"),
    required=False,
)
directives.widget(
    'my_data',
    AjaxSelectFieldWidget,
    vocabulary='my.vocab.options'
)
# multiple-input: (value1, value2)
my_data = schema.Tuple(
    title=_(u"My Data"),
    required=False,
    value_type=schema.TextLine(),
    missing_value=(),
)
directives.widget(
    'my_data',
    AjaxSelectFieldWidget,
    vocabulary='my.vocab.options'
)

<div tal:define="vals context/my_data|nothing"
     tal:condition="vals">
<tal:field i18n:translate="">My Data</tal:field>:
  <span tal:replace="python:view.t_title('my.vocab.options',vals[0])" />
</div>

Radio

Radio 和 Checkbox 的使用差異

Radio Button Widget: z3c.form.browser.radio.RadioFieldWidget

plone.app.widgets: Replace Specific DateTime Widgets in Plone 4.3 (pin versions for 4.3.3) and Replace All in Plone 5.x. upgrade from 1.4.0 to 1.6.0 (own jquery version)

讓 getVocabulary 在 non IPloneSiteRoot 情境裡也能運作

TextLinesFieldWidget 成為 plone.app.z3cform 預設值

Collective.z3cform.KeywordWidget

annotation with z3c.form DictionaryField Hide Disable Read Write Permission

Upload Reference Widget

Conditional Fields Static Field Non Editable: 利用 Behavior Adapter Class 的 Read/Write Property "initial_editor" 和 IObjectAddedEvent Subscriber。

TypeError: ('Could not adapt', <Item at /mysite/photos/my-item>, <InterfaceClass collective.geo.geographer.interfaces.IWriteGeoreferenced>)

TypeError: ('Could not adapt', <Item at >, <InterfaceClass plone.rfc822.interfaces.IPrimaryFieldInfo>)

Relation

RelationChoice 用於單值欄位,RelationList 用於多值欄位。

Plone 4.2 之前的 RelationChoice/RelationList ContentTree Widget 以 plone.formwidget.autocomplete 為基礎,使用 2008 年代的 JavaScript 程式碼,在 plone.formwidget.autocomplete 2.0 開始使用 JQueryUI

自訂 Dexterity 表單如果使用 Relation 欄位,應確認 setup.py 加進 plone.app.relationfield 相依關係,接著觀察是否會自動安裝相關套件 (在 Dexterity 1.0 時代會自動安裝),像是 plone.formwidget.contenttree, z3c.relationfield, plone.app.intid, five.intid, zope.intid, plone.formwidget.autocomplete, zc.relation, z3c.objpath, zope.app.container, zope.app.intid, zope.keyreference, zope.copypastemove;如果 (例如在 Dexterity 2.0 ) 預設沒有安裝 plone.formwidget.autocomplete 和 plone.formwidget.contenttree 必須考慮手動加進 setup.py 檔案。

Plone 5 預設內建 RelatedItemsWidget 不用再額外指定,但 Plone5 似乎朝 plone.app.vocabularies.catalog.CatalogSource 取代 Catalog 方向前進。

form.widget('slider_relation', RelatedItemsFieldWidget,
            vocabulary='plone.app.vocabularies.Catalog')
slider_relation = RelationList(
    title=_(u"Slider Banners"),
    description=_(u"These banners will be used in the slider"),
    default=[],
    value_type=RelationChoice(
        title=_(u'Target'),
        source=ObjPathSourceBinder(
            object_provides=IBanner.__identifier__,
        )),
    required=False,
)

想要使用別的 Widget 可以參考下列範例: 可以自動補齊,但只顯示比對到的文字,並無實際連到項目

from plone.autoform import directives
directives.widget('presenter', AutocompleteFieldWidget)

Dexterity Version vs Archetypes Version

from z3c.relationfield.schema import RelationList, RelationChoice
tags = RelationList(
    title = _(u'Tags'),
    default = [],
    value_type = RelationChoice(
        title = _(u'Tag'),
        source = ObjPathSourceBinder(
            navigation_tree_query = { ... },
            portal_type = 'Document',
        ),
    ),
    required = False,
)
tal:define="tpls context/temples|nothing"
tal:repeat="tpl tpls"
tpls type:list
tpl type:<class 'z3c.relationfield.relation.RelationValue'>
tpl.to_object type:<'Acquisition.ImplicitAcquisitionWrapper'>
tpl.to_id type:int

to_object 是 Relation 關係裡被指的物件,from_object 是起始物件。

指定搜尋目錄 path

z3c.form MultiWidget with RelationList as value_type

dictWithRelations = schema.Dict(
  title=u"Some Relations lists",
  required=False,
  key_type=schema.TextLine(title=_(u'afield')),
  value_type=relationfieldschema.RelationList(
    title=_(u'relations'),
    default=[],
    value_type=relationfieldschema.RelationChoice(
      source=CatalogSource(portal_type=['Document', 'Folder'])
    ),
    required=False,
  )
)

plone.portlet.collection 單一選項儲存 UID 的範例

uid = schema.Choice(
    title=_(u"Target Collection"),
    source=CatalogSource(portal_type=('Topic', 'Collection')),
)

plone.app.relationfield 搭配 plone.app.contenttypes 在刪除連結後不會同步更新,過渡解法是利用 isBroken 來檢查

ObjPathSourceBinder vs CatalogSource

  Module plone.app.content.browser.vocabulary, line 220, in __call__
TypeError: 'NoneType' object has no attribute '__getitem__'

plone.formwidget.contenttree 處理 Empty Reference 問題

Back References: [1] [2] navigation_tree_query

from Acquisition import aq_inner
from zope.component import getUtility
from zope.intid.interfaces import IIntIds
from zope.security import checkPermission
from zc.relation.interfaces import ICatalog

def back_references(source_object, attribute_name):
    """ Return back references from source object on specified attribute_name """
    catalog = getUtility(ICatalog)
    intids = getUtility(IIntIds)
    result = []
    for rel in catalog.findRelations(
                            dict(to_id=intids.getId(aq_inner(source_object)),
                                 from_attribute=attribute_name)
                            ):
        obj = intids.queryObject(rel.from_id)
        if obj is not None and checkPermission('zope2.View', obj):
            result.append(obj)
    return result

eea.relations

RelationChoice integration LookupError bug in Plone 4.3.3 RadioWidgets fails when the value is '--NOVALUE--' (self.noValueToken) Solgema.fullcalendar

z3c.relationfield 內建 Relation 欄位和 RelationValue 物件,透過 zc.relation 可以建立索引,透過 z3c.relationfieldui 可以建立使用者介面。

related_gender = z3c.relationfield.schema.RelationChoice(
  title=u'Related item',
  source=GenderSourceFactory(),
  required=False)

z3c.relationfield + BackReferences

Date Time

Plone 4.3.10 未啟用 plone.app.contenttypes 前,預設並不會安裝 plone.app.event,日期時間 Widget 使用傳統版本;啟用 plone.app.contenttypes 後,同時會啟用 plone.app.event。

the default datetime widget for dexterity < Plone 5:

https://github.com/collective/collective.z3cform.datetimewidget

the default datetime widget for plone.app.event < 1.2:

https://github.com/plone/plone.formwidget.datetime

this will be used in Plone 5 for most widgets and can already be used in Plone 4.3:

https://github.com/plone/plone.app.widgets

Date Only

from zope import schema

date = schema.Date( title=_("Date"), )

Set Year Range collective.z3cform.datetimewidget 可以指定 min/max 值

from collective.z3cform.datetimewidget import DateWidget    
...
form.widget('birthday', DateWidget)
birthday = schema.Date(
  title=_(u'Birthday'),
  description=_(u'your birthday'),
  required=True,
  min = date(1950,1,1),
  max = date(2015,1,1))

plone.formwidget.datetime Allows Empty Values jQuery Calendar Updated When Selection Changed dateable.chronos: calendar view

plone.formwidget.multifile: use plone.namedfile.interfaces.IFile instead of zope.app.file.interfaces.IFile plone.formwidget.recurrence Remove plone.formwidget.datetime Dependency

TypeError: 'datetime.datetime' object has no attribute 'getitem'

Change z3c.form Date Widget with JavaScript

When user wants to set Date or Datetime value and missed one of the fields (day, year, hour or minute) it silently sets it to None without error messages which input is not valid.

控制起始與結束日期在特定的年份期間內 HTML5 範例

<form action="action_page.php">
  Quantity (between 1 and 5):
  <input type="number" name="quantity" min="1" max="5">
  <input type="submit">
</form>

eea.facetednavigation: Date Widget Reset Relative Date Widget Reset

Calendar

FullCalendar for Plone5

https://www.npmjs.com/package/snow-calendar

DataGrid

howto: Add collective.z3cform.datagridfield to buildout.cfg

Edit my_content.py

from collective.z3cform.datagridfield import DataGridFieldFactory
from collective.z3cform.datagridfield import BlockDataGridFieldFactory

Create the schema for the table

class IAddress(form.Schema):
  address = schema.TextLine(
    title=(u"Address?"),
    required=True,
  )

Add it to the form schema

form.widget(address=BlockDataGridFieldFactory)
address = schema.List(title=u"Address", required=False,
value_type=DictRow(title=u"Address", schema=IAddress, required=False))

Model Example: 注意 <defaultFactory /> 的設定位置

<field name="events" type="zope.schema.List"
 form:widget="collective.z3cform.datagridfield.DataGridFieldFactory">
  <title>Events</title>
  <value_type type="collective.z3cform.datagridfield.DictRow">
  <title>Events</title>
  <schema>myswimmingclub.content.swimming_meet_event.ISwimmingMeetEvent</schema>
  </value_type>
  <defaultFactory>myswimmingclub.content.defaults.DefaultStrokesFactory</defaultFactory>
</field>

Context is no present in Vocabulary Factory

<field name="articles_list" type="zope.schema.Choice" lingua:independent="true">
  <description />
  <required>False</required>
  <title>Article List</title>
  <vocabulary>mdb_theme.ArticlesVocabulary</vocabulary>
</field>

collective.z3cform.datagridfield sample code move collective.z3cform.datagridfield_demo separately pass list values for a choice field in a datagrid field in dexterity Vocabulary NO_VALUE DataGrid Inside DataGrid select2 widget

Custom Widget with Vocabulary

class MyWidget(CheckBoxWidget):
    ...
    @property
    def terms(self):
        catalog = getToolByName(self.context, 'portal_catalog')
        content = catalog(
            portal_type='my.type',
        )
        return SimpleVocabulary([SimpleTerm(x.id, x, title=x.Title) for x in content])

z3c.form 3.3 改版後的影響 Plone5

RelationChoice Z3CFormValidation getSite() KSS

Using Relation patternslib clone for repeating fields

collective.datagridcolumns: DataGrid Field 延伸模組

MasterSelect

plone.formwidget.masterselect: plone5

MultiValue

collective.taxonomy: TaxonomySelectWidget: collective.z3cform.select2

Multiple File Field Widget

Archetypes SelectionWidget Needs Populated

RichWidget URL Conversion by plone.outputfilter Plone5 的 plone.outputfilter 預設都是啟用 link-by-uid

Dictionary Key Value

依照欄位狀況來決定是否顯示

欄位描述文字轉換成提示模式 Progress Bar Widget collective.upload

Model Driven Forms and Custom Fields

和 plone.app.registry GenericSetup 搭配的注意事項

#13450 datetime

Related Field: PloneConf 2012 UI Sprint Content Finder Demo from Mockup into plone.app.widgets

TokenInputFieldWidget: all keywords are loaded trimmed keywords

collective.z3cform.widgets 1.0b10 解決了 related.js 與 plone.formwidget.contenttree 衝突 draggable behaviour for entire page

plone.app.widgets

RelatedItemsWidget

zc.relation/z3c.relationship/plone.app.relationfield is a successor to zc.relationship/plone.relations/plone.app.relations.

collective.z3cform.datetimewidget min-max support

GeoLocation

Plone 早期有 Location 欄位,自由選填,沒有特別被應用。

EEA Geotags 提供 Map Picker 和 GeoNames 的查詢。

collective.z3cform.mapwidget 通常搭配 zope.schema.TextLine 使用

plone.formwidget.geolocation: leaflet maps integration

collective.geolocationbehavior

Model XML File

透過 plone.supermodel 可以使用 XML 格式來存取 Schema 設定值。

Multiple Selection 可參考 plone.app.layout/viewlets/keywords.pt 的 Filed under 範例修改 Template 來顯示多值

<field name="links" type="zope.schema.List">
  <title>Related Items</title>
  <value_type type="zope.schema.Choice">
    <title>Related</title>
    <source>plone.supermodel.tests.dummy_binder</source>
  </value_type>
</field>

plone.supermodel XML Choosing Different Widgets Unicode-handling of Integer Values for IChoice

在 import 之前要先 load ZCML,不然會遇到 SupermodelParseError 錯誤。

Radio Button z3c.form.browser.radio RadioWidget

Obsolete RecurrenceField and use StringField

Remove annotation storage in behavior fields

base_edit Customization

Embedding z3c.form widget into Archetypes base_edit form

collective.tablepage Archetypes based

Primary Field

TypeError 'Could not adapt' IPrimaryFieldInfo

from plone.directives import form
from zope import schema

class IMyContentType(form.Schema):
    """ """
    form.primary('some_field')
    some_field = schema.TextLine(
        title=u"Some field",
    )

    another_field = schema.TextLine(
        title=u"Another field",
    )

搜尋指定欄位,例如所有 Image 欄位:

from plone.app.blob.interfaces import IBlobImageField
from plone.dexterity.utils import iterSchemata
from plone.namedfile.interfaces import INamedImageField
from zope.schema import getFieldsInOrder

...
        image_fields = []
        if getattr(aq_base(obj), 'Schema', None):
            # Archetypes
            for field in obj.Schema().values():
                if not (IBlobImageField.providedBy(field) or
                        INamedImageField.providedBy(field)):
                    continue
                image_fields.append(field)
        else:
            # Dexterity
            for schemata in iterSchemata(obj):
                fields = getFieldsInOrder(schemata)
                for name, field in fields:
                    if not (IBlobImageField.providedBy(field) or
                            INamedImageField.providedBy(field)):
                        continue
                    image_fields.append(field)
        # Now iterate over all fields, whether AT or dexterity.
        for field in image_fields:
            field_instance = field.get(obj)

Getter and Setter

plone.supermodel 的 form 和 security 兩個 namespace 可以透過 plone.autoform Handler 來控制。

Solgema.ContextualContentMenu: Adds a right click menu that shows Plone's content and action menu

HTML Map Tag ImageMap

collective.embedly 文件

<model xmlns:i18n="http://xml.zope.org/namespaces/i18n"
       xmlns:security="http://namespaces.plone.org/supermodel/security"
       xmlns:marshal="http://namespaces.plone.org/supermodel/marshal"
       xmlns:form="http://namespaces.plone.org/supermodel/form"
       xmlns="http://namespaces.plone.org/supermodel/schema">
  <schema>
    <field name="start_date" type="zope.schema.Date">
      <description/>
      <title>Start Date</title>
    </field>
    <field name="end_date" type="zope.schema.Date">
      <description/>
      <required>False</required>
      <title>End Date</title>
    </field>
    <field name="yes_no" type="zope.schema.Bool">
      <description/>
      <required>False</required>
      <title>Yes No</title>
      <form:widget type="z3c.form.browser.radio.RadioFieldWidget"/>
    </field>
    <field name="single_choice" type="zope.schema.Choice">
      <description/>
      <required>False</required>
      <title>Single Choice</title>
      <values>
        <element>Choice A</element>
        <element>Choice B</element>
      </values>
    </field>
    <field name="multiple_choice" type="zope.schema.Set">
      <description/>
      <required>False</required>
      <title>Multiple Choice</title>
      <value_type type="zope.schema.Choice">
        <values>
          <element>Item A</element>
          <element>Item B</element>
          <element>Item C</element>
        </values>
      </value_type>
    </field>
  </schema>
</model>
start_date = schema.Date(
    title=_(u'Start Date'),
  )

yes_no = schema.Bool(
    title=_(u'Yes No'),
)
directives.widget('yes_no', RadioFieldWidget) # not tested

single_choice = schema.Choice(
    title=_(u'Single Choice'),
    required=False,
    vocabulary=single_option,
)

multi_choice = schema.Set(
    title=_(u'Multiple Choice'),
    required=False,
    value_type=schema.Choice(
        vocabulary=multi_option,
    )
)
Related content
Behaviors