跳转到主要内容

将用户可输入的搜索条件表单添加到集合中。

项目描述

此包扩展了Products.ATContentTypes.criteria类型以创建搜索表单。具体来说,每个标准中在“表单字段”中选定的任何标准字段都将渲染在搜索表单上。在标准编辑表单上设置的值成为搜索表单上的默认值。通过搜索表单提交的搜索词补充了搜索表单上未包含的任何标准。也就是说,未出现在表单上的标准成为内置在搜索表单中的基础查询。

提供了一种新的“搜索表单”显示布局,该布局渲染搜索表单和集合正文文本,但不显示结果。此布局上的搜索表单将使用集合编辑表单中“表单结果布局”字段指定的布局来显示结果。

搜索表单还可以根据plone.portlet.collection渲染为一个基于搜索表单的端口号。该端口号不会在搜索表单视图或条件编辑表单上渲染,但根据端口号设置渲染指定集合的搜索表单。

因此,集合可以使用搜索表单或结果列表作为显示布局。用户可以使用表单或端口号启动搜索。端口号还反映了任何提交的搜索词,因此为用户提供了一种方便的方式来细化他们的搜索。

还可以添加多个排序条件,这将渲染用户可选择的排序链接到批处理宏中。有关更多详细信息,请参阅collective/formcriteria/criteria/sort.rst。

还提供了一个CSV导出操作,该操作为用户提供了一个下载集合结果的链接,前提是用户以CSV格式进行查询。这允许将集合用于与电子表格软件结合使用进行临时报告或有限导出到其他系统。

还包括了文件夹内容表的显示布局。此布局尚未完全功能化,但提供了构建一些非常丰富的网站管理功能的基础。

警告:卸载

在添加任何集合或向任何集合添加条件(即使是在安装前添加的)后卸载此产品未经测试,可能会导致您的集合损坏。

表单标准

从搜索结果的一些内容开始。

>>> from plone.app import testing
>>> from Products.CMFCore.utils import getToolByName
>>> portal = layer['portal']
>>> membership = getToolByName(portal, 'portal_membership')
>>> folder = membership.getHomeFolder(testing.TEST_USER_ID)
>>> testing.login(portal, testing.TEST_USER_NAME)
>>> folder['bar-document-title']
<ATDocument at /plone/Members/test_user_1_/bar-document-title>
>>> folder['baz-event-title']
<ATEvent at /plone/Members/test_user_1_/baz-event-title>

打开浏览器并以普通用户身份登录。

>>> from plone.testing import z2
>>> browser = z2.Browser(layer['app'])
>>> browser.handleErrors = False
>>> browser.open(portal.absolute_url())
>>> browser.getLink('Log in').click()
>>> browser.getControl('Login Name').value = testing.TEST_USER_NAME
>>> browser.getControl(
...     'Password').value = testing.TEST_USER_PASSWORD
>>> browser.getControl('Log in').click()

添加并发布一个集合。

>>> browser.open(folder.absolute_url())
>>> browser.getLink('Collection').click()
>>> browser.getControl('Title').value = 'Foo Topic Title'
>>> browser.getControl('Save').click()
>>> print browser.contents
<...
...Changes saved...
>>> foo_topic = folder['foo-topic-title']
>>> browser.getLink('Submit').click()
>>> print browser.contents
<...
...Item state changed...
>>> z2.login(portal.getPhysicalRoot().acl_users, testing.SITE_OWNER_NAME)
>>> layer['portal'].portal_workflow.doActionFor(foo_topic, 'publish')
>>> testing.login(portal, testing.TEST_USER_NAME)
>>> import transaction
>>> transaction.commit()

将集合的显示布局更改为“搜索表单”。

>>> browser.getLink('Search Form').click()
>>> print browser.contents
<...
...View changed...

以可以管理端口号的用户身份登录。

>>> owner_browser = z2.Browser(layer['app'])
>>> owner_browser.handleErrors = False
>>> owner_browser.open(portal.absolute_url())
>>> owner_browser.getLink('Log in').click()
>>> owner_browser.getControl(
...     'Login Name').value = testing.SITE_OWNER_NAME
>>> owner_browser.getControl(
...     'Password').value = testing.TEST_USER_PASSWORD
>>> owner_browser.getControl('Log in').click()

将此集合的搜索表单端口号添加到文件夹中。

>>> owner_browser.open(folder.absolute_url())
>>> owner_browser.getLink('Manage portlets').click()
>>> owner_browser.getControl(
...     'Search form portlet', index=1).selected = True
>>> owner_browser.getForm(index=3).submit() # manually w/o JS
>>> print owner_browser.contents
<...
...Add Search Form Portlet...
>>> header = owner_browser.getControl('Portlet header')
>>> header.value = 'Foo Search Form Title'
>>> foo_topic_path = '/'.join(
...     ('',)+ foo_topic.getPhysicalPath()[
...         len(portal.getPhysicalPath()):])
>>> header.mech_form.new_control(
...     type='checkbox', name="form.target_collection",
...     attrs=dict(checked='checked', value=foo_topic_path))
>>> owner_browser.getControl('Save').click()
>>> print owner_browser.contents
<...
...Foo Search Form Title...

转到集合的编辑选项卡并设置“表单结果布局”字段。

>>> browser.getLink('Edit').click()
>>> browser.getControl('Collection').selected = True
>>> browser.getControl('Save').click()
>>> print browser.contents
<...
...Changes saved...

转到“条件”选项卡,并为工作流状态添加一个不会出现在表单上的条件。然后设置查询词以仅返回已发布的内容。

>>> browser.getLink('Criteria').click()
>>> form = browser.getForm(name='criteria_select')
>>> form.getControl('State').selected = True
>>> form.getControl(
...     'Select values from list', index=1).selected = True
>>> form.getControl('Add criteria').click()
>>> print browser.contents
<...
...State...
...Select values from list...

由于测试浏览器没有JavaScript,请手动通过索引手动测试条件类型的区分。

>>> foo_topic.allowedCriteriaForField('review_state')
['FormSelectionCriterion', 'FormCheckboxCriterion',
'FormPulldownCriterion', 'FormSimpleStringCriterion',
'FormListCriterion', 'FormCommaCriterion', 'FormSortCriterion',
'FormContextCriterion']
>>> foo_topic.allowedCriteriaForField(
...     'review_state', display_list=True)
<DisplayList
[('FormSelectionCriterion', 'Select values from list'),
 ('FormCheckboxCriterion', 'Check values'),
 ('FormPulldownCriterion', 'Select one value'),
 ('FormSimpleStringCriterion', 'Text'),
 ('FormListCriterion', 'List of values'),
 ('FormCommaCriterion', 'Enter comma separated values'),
 ('FormSortCriterion', 'Sort results'),
 ('FormContextCriterion',
  'Values will be taken from the context')] at ...>

设置查询词并保存。

>>> form = browser.getForm(action="criterion_edit_form", index=0)
>>> form.getControl('published').selected = True
>>> form.getControl('Save').click()
>>> print browser.contents
<...
...Changes saved...

以匿名用户身份打开另一个浏览器。

>>> anon_browser = z2.Browser(layer['app'])
>>> anon_browser.handleErrors = False

在主题有任何表单条件之前,搜索表单不存在。

>>> anon_browser.open(foo_topic.absolute_url()+'/atct_topic_view')
>>> anon_browser.getForm(name="formcriteria_search")
Traceback (most recent call last):
LookupError

在条件选项卡上为SearchableText索引添加一个简单的字符串条件。

>>> form = browser.getForm(name='criteria_select')
>>> form.getControl('Search Text').selected = True
>>> form.getControl(name="criterion_type").getControl(
...     'Text', index=1).selected = True
>>> form.getControl('Add criteria').click()
>>> print browser.contents
<...
...Search Text...
...A simple string criterion...

将条件的“值”字段作为表单字段选择,以便它在搜索表单上显示。

>>> browser.getControl(
...     name='crit__SearchableText_FormSimpleStringCriterion'
...     '_formFields:list').getControl('Value').selected = True

设置默认搜索词。

>>> browser.getControl(
...     name="crit__SearchableText_FormSimpleStringCriterion"
...     "_value").value = 'bar'
>>> browser.getControl(name="form.button.Save").click()
>>> print browser.contents
<...
...Changes saved...

如果没有提交表单值,例如在主题视图的新加载中,将使用默认词进行查询,仅返回一个内容对象。

>>> len(foo_topic.queryCatalog())
1
>>> anon_browser.open(foo_topic.absolute_url()+'/atct_topic_view')
>>> anon_browser.getLink('Bar Document Title')
<Link text='...Bar Document Title'
url='http://nohost/plone/Members/test_user_1_/bar-document-title'>
>>> anon_browser.getLink('Baz Event Title')
Traceback (most recent call last):
LinkNotFoundError

现在已添加表单条件,搜索表单已渲染。

>>> anon_browser.open(foo_topic.absolute_url())
>>> form = anon_browser.getForm(name="formcriteria_search")
>>> 'formcriteria-portlet.css' in anon_browser.contents
True

未在选择“表单字段”中选择的条件字段不会出现在搜索表单上。

>>> form.getControl(
...     name='form_crit__SearchableText_FormSimpleStringCriterion'
...     '_formFields:list')
Traceback (most recent call last):
LookupError: name
'form_crit__SearchableText_FormSimpleStringCriterion_formFields:list'

条件的标签对应于第一个条件字段表单元素。

>>> ctl = form.getControl('Search Text')

输入搜索词并提交查询。现在主题将列出其他内容对象。

>>> ctl.value = 'baz'
>>> form.getControl(name='submit').click()
>>> anon_browser.getLink('Bar Document Title')
Traceback (most recent call last):
LinkNotFoundError
>>> anon_browser.getLink('Baz Event Title')
<Link text='...Baz Event Title'
url='http://nohost/plone/Members/test_user_1_/baz-event-title'>

由于已提交搜索表单,结果将根据“表单结果布局”指定的布局进行渲染。

>>> anon_browser.url.startswith(
...     'http://nohost/plone/Members/test_user_1_/foo-topic-title'
...     '/atct_topic_view')
True

搜索表单端口号还反映了在条件选项卡上提交的搜索词,而不是默认值。

>>> form = anon_browser.getForm(name="formcriteria_search")
>>> ctl = form.getControl('Search Text')
>>> ctl.value
'baz'

如果从该页面提交搜索表单,结果仍然会在同一视图中渲染。

>>> ctl.value = 'bar'
>>> form.getControl(name='submit').click()
>>> anon_browser.url.startswith(
...     'http://nohost/plone/Members/test_user_1_/foo-topic-title'
...     '/atct_topic_view')
True

如果提交的是不在“表单字段”中列出的条件字段,则这些值也会被忽略。

>>> crit = foo_topic.getCriterion(
...     'SearchableText_FormSimpleStringCriterion')
>>> crit.setFormFields([])
>>> transaction.commit()
>>> anon_browser.open(
...     foo_topic.absolute_url()+'/atct_topic_view'
...     '?form_crit__SearchableText_FormSimpleStringCriterion'
...     '_value=baz')
>>> anon_browser.getLink('Bar Document Title')
<Link text='...Bar Document Title'
url='http://nohost/plone/Members/test_user_1_/bar-document-title'>
>>> anon_browser.getLink('Baz Event Title')
Traceback (most recent call last):
LinkNotFoundError
>>> crit.setFormFields(['value'])
>>> import transaction
>>> transaction.commit()

搜索表单能够优雅地处理索引查询解析错误,并向用户显示消息。

>>> anon_browser.open(foo_topic.absolute_url())
>>> form = anon_browser.getForm(name="formcriteria_search")
>>> ctl = form.getControl('Search Text')
>>> ctl.value = 'bar (baz)'
>>> form.getControl(name='submit').click()
>>> print anon_browser.contents
<...There are currently no results for this search...
>>> anon_browser.getLink('Bar Document Title')
Traceback (most recent call last):
LinkNotFoundError
>>> anon_browser.getLink('Baz Event Title')
Traceback (most recent call last):
LinkNotFoundError

当在非表单上下文中查看时,搜索表单组件可以成功渲染。

>>> anon_browser.open(folder.absolute_url())
>>> form = anon_browser.getForm(name="formcriteria_search")

确保 collective.formcriteria 不会破坏现有的 ATTopic 实例,例如在 Plone 网站中默认创建的实例。

>>> owner_browser.open(portal.news.absolute_url())
>>> print owner_browser.contents
<...
...Site News...
...There are currently no items in this folder...
>>> owner_browser.getLink('Edit').click()
>>> print owner_browser.contents
<...
... Search terms ...

确保 collective.formcriteria 的任何扩展都不会干扰现有的 ATTopic 实例。

>>> browser.open(portal.events.aggregator.absolute_url())

所有条件也可以使用 poral_types.constructContent 创建。

>>> z2.login(portal.getPhysicalRoot().acl_users, testing.SITE_OWNER_NAME)
>>> foo_topic.deleteCriterion(
...     'crit__SearchableText_FormSimpleStringCriterion')
>>> foo_topic.deleteCriterion(
...     'crit__review_state_FormSelectionCriterion')
>>> seen = set()
>>> topic_indexes = portal.portal_atct.topic_indexes
>>> for field, index in sorted(topic_indexes.iteritems()):
...     for criterion in index.criteria:
...         if criterion in seen or criterion.startswith('AT'):
...             continue
...         portal.portal_types.constructContent(
...             criterion, foo_topic,
...             id='crit__%s_%s' % (field, criterion))
...         seen.add(criterion)
'crit__Creator_FormSelectionCriterion'
'crit__Creator_FormCheckboxCriterion'
'crit__Creator_FormPulldownCriterion'
'crit__Creator_FormSimpleStringCriterion'
'crit__Creator_FormListCriterion'
'crit__Creator_FormCommaCriterion'
'crit__Creator_FormSortCriterion'
'crit__Creator_FormContextCriterion'
'crit__Date_FormDateCriterion'
'crit__Date_FormDateRangeCriterion'
'crit__Type_FormPortalTypeCriterion'
'crit__Type_FormPortalTypeCheckboxCriterion'
'crit__Type_FormPortalTypePulldownCriterion'...
'crit__path_FormPathCriterion'
'crit__path_FormRelativePathCriterion'

安装

通过 Plone 扩展控制面板安装 collective.formcriteria 时,使用的是“默认”配置文件。

>>> portal.portal_quickinstaller.uninstallProducts(['collective.formcriteria'])
>>> print portal.portal_quickinstaller.installProducts(['collective.formcriteria'])
    Installed Products
    ====================
    collective.formcriteria:ok:
>>> portal.portal_quickinstaller.getInstallProfiles(
...     'collective.formcriteria')[0]
u'collective.formcriteria:default'

排序

支持两种排序条件。可以定义多个固定排序条件,允许用户通过批量宏的链接从中选择。每个集合可以添加一个表单排序条件,以便用户在排序表单上指定排序。如果两者都使用,并且用户从表单和批量链接中提交了排序,则列表中最后的排序条件生效。

表单排序条件尚未实现。

固定排序标准

将项目计数设置为 1,以便批量只包含一个项目。

>>> from Products.CMFCore.utils import getToolByName
>>> portal = layer['portal']
>>> membership = getToolByName(portal, 'portal_membership')
>>> from plone.app import testing
>>> folder = membership.getHomeFolder(testing.TEST_USER_ID)
>>> foo_topic = folder['foo-topic-title']
>>> foo_topic.setItemCount(1)
>>> import transaction
>>> transaction.commit()

打开浏览器并以普通用户身份登录。

>>> from plone.testing import z2
>>> from plone.app import testing
>>> portal = layer['portal']
>>> browser = z2.Browser(layer['app'])
>>> browser.handleErrors = False
>>> browser.open(portal.absolute_url())
>>> browser.getLink('Log in').click()
>>> browser.getControl('Login Name').value = testing.TEST_USER_NAME
>>> browser.getControl(
...     'Password').value = testing.TEST_USER_PASSWORD
>>> browser.getControl('Log in').click()

加载集合的条件编辑表单。

>>> browser.open(foo_topic.absolute_url())
>>> browser.getLink('Criteria').click()

排序选择表单已从条件标签中移除。

>>> browser.getForm(action="criterion_edit_form", index=1)
Traceback (most recent call last):
IndexError: list index out of range

相反,可以通过在条件标签的正常条件添加表单中添加多个排序条件。

>>> form = browser.getForm(name="criteria_select")
>>> form.getControl('Relevance').selected = True
>>> form.getControl('Sort results').selected = True
>>> form.getControl('Add criteria').click()
>>> print browser.contents
<...
...Added criterion FormSortCriterion for field unsorted...

为日期字段添加另一个反向排序条件。

>>> form = browser.getForm(name="criteria_select")
>>> form.getControl('Effective Date').selected = True
>>> form.getControl('Sort results').selected = True
>>> form.getControl('Add criteria').click()
>>> print browser.contents
<...
...Added criterion FormSortCriterion for field effective...

将集合的显示布局更改为“搜索表单”,然后提交搜索条件以测试排序链接是否保留搜索条件。

>>> foo_topic.setLayout('criteria_form')
>>> foo_topic.addCriterion(
...     'SearchableText','FormSimpleStringCriterion'
...     ).setFormFields(['value'])
>>> import transaction
>>> transaction.commit()
>>> browser.getLink('View').click()
>>> form = browser.getForm(name="formcriteria_search")
>>> form.getControl('Search Text').value = 'blah'
>>> form.getControl(name='submit').click()

当批量宏在集合视图中渲染时,例如列表之一,它将包括按顺序排列的不同可能的排序链接。默认情况下,选择第一个排序条件。排序链接还具有用于样式支持的 id 和 CSS 类。

>>> print browser.contents
<...
          Sort on:
            <span class="formcriteriaSortField selected">Relevance</span>
            <button...>Effective Date</button>
...
>>> form = browser.getForm(name="navigation_form")
>>> form.getControl(
...     name="crit__unsorted_FormSortCriterion:boolean")
Traceback (most recent call last):
LookupError: name
'crit__unsorted_FormSortCriterion:boolean'

结果按权重顺序列出。

>>> browser.getLink('Baz Event Title')
<Link text='...Baz Event Title'
url='http://nohost/plone/Members/test_user_1_/baz-event-title'>
>>> browser.getLink('Bar Document Title')
Traceback (most recent call last):
LinkNotFoundError

单击排序链接时,该排序将显示为选中状态,并且结果将根据排序条件排序。

>>> form = browser.getForm(name="navigation_form")
>>> form.getControl(
...     name="crit__effective_FormSortCriterion:boolean").click()
>>> print browser.contents
<...
...Sort on:...
...Relevance...
...Effective Date</span>...
>>> form = browser.getForm(name="navigation_form")
>>> form.getControl(
...     name="crit__effective_FormSortCriterion:boolean")
<Control name='crit__effective_FormSortCriterion:boolean' type='hidden'>
>>> form = browser.getForm(name="navigation_form")
>>> form.getControl(
...     name="crit__unsorted_FormSortCriterion:boolean")
<SubmitControl name='crit__unsorted_FormSortCriterion:boolean'
type='submitbutton'>

结果反映了搜索查询在新排序选择中得到了保留。

>>> browser.getLink('Bar Document Title')
<Link text='...Bar Document Title'
url='http://nohost/plone/Members/test_user_1_/bar-document-title'>
>>> browser.getLink('Baz Event Title')
Traceback (most recent call last):
LinkNotFoundError

如果选择了下一批,则排序和搜索查询将得到保留。

>>> form = browser.getForm(name="navigation_form")
>>> form.getControl(name="b_start", index=0).click()
>>> browser.getLink('Bar Document Title')
Traceback (most recent call last):
LinkNotFoundError
>>> browser.getLink('Baz Event Title')
<Link text='...Baz Event Title'
url='http://nohost/plone/Members/test_user_1_/baz-event-title'>

即使只有一个批量,批量宏也会渲染排序链接。

>>> foo_topic.setItemCount(0)
>>> import transaction
>>> transaction.commit()
>>> browser.open(foo_topic.absolute_url()+'/atct_topic_view')
>>> form = browser.getForm(name="navigation_form")
>>> form.getControl(
...     name="crit__effective_FormSortCriterion:boolean")
<SubmitControl name='crit__effective_FormSortCriterion:boolean'
type='submitbutton'>

确保扩展的排序条件可以在之前创建的 ATTopic 实例内部正常工作。

>>> topic = folder['at-topic-title']
>>> topic.setSortCriterion('effective', True)
>>> topic.queryCatalog()[0].getObject()
<ATEvent at /plone/Members/test_user_1_/baz-event-title>

分组列表

提供了一种默认集合视图的变体,它按使用的排序分组列出项目。这需要用于排序的索引也位于目录元数据列中,并且在目录大脑中可用。

按创建者排序,以便我们至少有一个包含多个项目的组。

>>> foo_topic.deleteCriterion('crit__unsorted_FormSortCriterion')
>>> foo_topic.setSortCriterion('Creator', False)
>>> import transaction
>>> transaction.commit()

选择布局。

>>> browser.open(foo_topic.absolute_url())
>>> browser.getLink('Grouped Listing').click()
>>> print browser.contents
<...
...View changed...
>>> browser.getLink('Log out').click()

现在项目按排序值分组。

>>> browser.open(foo_topic.absolute_url())
>>> print browser.contents
<...
...<dl...
...<dt...bar_creator_id...</dt>...
...<dd...
...Baz Event Title...
...</dd...
...<dt...foo_creator_id...</dt>...
...<dd...
...Foo Event Title...
...Bar Document Title...
...</dd...
...</dl>...

分组列表布局需要排序条件来渲染,如果没有排序条件,则会引发错误。

>>> foo_topic.deleteCriterion('crit__Creator_ATSortCriterion')
>>> import transaction
>>> transaction.commit()
>>> browser.open(foo_topic.absolute_url())
Traceback (most recent call last):
AssertionError: ...

即使没有排序条件,批量宏仍然适用于主题。

>>> foo_topic.setLayout('criteria_form')
>>> import transaction
>>> transaction.commit()
>>> browser.open(foo_topic.absolute_url())
>>> form = browser.getForm(name="formcriteria_search")
>>> form.getControl('Search Text').value = 'blah'
>>> form.getControl(name='submit').click()
>>> 'Sort on:' in browser.contents
False

CSV导出

从集合中以表格形式访问的数据通常是站点管理员想要导出到其他格式(如 CSV)的精确数据。此包提供视图,将当前查询的集合数据导出到各种格式。CSV 列来自集合的“表列”字段,位于编辑标签/表单上,无论是否使用表格布局。CSV 导出链接作为文档操作(如打印和发送操作)提供。

更改列和链接列。

>>> from plone.testing import z2
>>> from plone.app import testing
>>> portal = layer['portal']
>>> z2.login(portal.getPhysicalRoot().acl_users, testing.SITE_OWNER_NAME)
>>> from Products.CMFCore.utils import getToolByName
>>> membership = getToolByName(portal, 'portal_membership')
>>> folder = membership.getHomeFolder(testing.TEST_USER_ID)
>>> foo_topic = folder['foo-topic-title']
>>> columns = foo_topic.columns
>>> columns.manage_delObjects(
...     ['ModificationDate-column', 'get_size-column',
...      'review_state-column'])
>>> columns['getPath-column'].update(filter='')
>>> columns['Title-column'].update(link=False, sort='')
>>> desc_column = columns[columns.invokeFactory(
...     type_name='TopicColumn', id='Description-column',
...     link=True)]
>>> foo_topic.manage_delObjects(
...     ['crit__sortable_title_FormSortCriterion',
...      'crit__get_size_FormSortCriterion',
...      'crit__modified_FormSortCriterion',
...      'crit__review_state_FormSortCriterion'])
>>> testing.logout()

向集合添加一些条件。

>>> _ = foo_topic.addCriterion(
...     'path', 'FormRelativePathCriterion')
>>> foo_topic.addCriterion(
...     'Type', 'FormSelectionCriterion'
...     ).setValue(['Page', 'Event'])
>>> foo_topic.getCriterion(
...     'SearchableText_FormSimpleStringCriterion'
...     ).setFormFields(['value'])
>>> _ = foo_topic.addCriterion(
...     'unsorted', 'FormSortCriterion')
>>> _ = foo_topic.addCriterion(
...     'effective', 'FormSortCriterion')
>>> import transaction
>>> transaction.commit()

打开浏览器并以普通用户身份登录。

>>> browser = z2.Browser(layer['app'])
>>> browser.handleErrors = False
>>> browser.open(portal.absolute_url())
>>> browser.getLink('Log in').click()
>>> browser.getControl('Login Name').value = testing.TEST_USER_NAME
>>> browser.getControl(
...     'Password').value = testing.TEST_USER_PASSWORD
>>> browser.getControl('Log in').click()

导出链接现已可用。下载未查询的原始集合结果。

>>> browser.open(foo_topic.absolute_url())
>>> export_link = browser.getLink('Export')
>>> export_link.click()
>>> browser.isHtml
False
>>> print browser.headers
Status: 200 ...
Content-Disposition: attachment...
Content-Type: text/csv...

由于测试浏览器无法处理文件下载,我们将通过直接调用浏览器视图来检查CSV输出。

>>> from zope import interface
>>> from collective.formcriteria import interfaces
>>> interface.alsoProvides(layer['request'], interfaces.IFormCriteriaLayer)
>>> from collective.formcriteria.testing import export
>>> print export(portal, foo_topic, layer['request'], export_link.url)
Status: 200 OK...
Content-Type: text/csv
Content-Disposition: attachment;filename=foo-topic-title.csv
URL,Title,Description
http://nohost/plone/Members/test_user_1_/foo-event-title,Foo Event Title,
http://nohost/plone/Members/test_user_1_/bar-document-title,Bar Document Title,blah
http://nohost/plone/Members/test_user_1_/baz-event-title,Baz Event Title,blah blah
>>> testing.logout()

添加搜索表单组件。

>>> from zope import component
>>> from plone.i18n.normalizer import (
...     interfaces as normalizer_ifaces)
>>> from collective.formcriteria.portlet import portlet
>>> testing.login(portal, testing.TEST_USER_NAME)
>>> manager = foo_topic.restrictedTraverse(
...     '++contextportlets++plone.rightcolumn')
>>> site_path_len = len(portal.getPhysicalPath())
>>> assignment = portlet.Assignment(
...     header='Foo Search Form Title',
...     target_collection='/'.join(
...         foo_topic.getPhysicalPath()[site_path_len:]))
>>> name = component.getUtility(
...     normalizer_ifaces.IIDNormalizer).normalize(
...         assignment.title)
>>> manager[name] = assignment
>>> testing.logout()
>>> import transaction
>>> transaction.commit()

提交查询。导出的CSV反映了用户提交的查询,并按相关性排序。

>>> browser.open(foo_topic.absolute_url())
>>> form = browser.getForm(name="formcriteria_search")
>>> form.getControl('Search Text').value = 'blah'
>>> form.getControl(name='submit').click()
>>> export_link = browser.getLink('Export')
>>> export_link.click()
>>> browser.isHtml
False
>>> print browser.headers
Status: 200...
Content-Disposition: attachment;filename=foo-topic-title.csv
Content-Length: ...
Content-Type: text/csv...
>>> print export(portal, foo_topic, layer['request'], export_link.url)
URL,Title,Description
http://nohost/plone/Members/test_user_1_/baz-event-title,Baz Event Title,blah blah
http://nohost/plone/Members/test_user_1_/bar-document-title,Bar Document Title,blah

选择其他排序方式,导出的CSV反映了用户选择的排序和查询。

>>> browser.open(foo_topic.absolute_url())
>>> form = browser.getForm(name="formcriteria_search")
>>> form.getControl('Search Text').value = 'blah'
>>> form.getControl(name='submit').click()
>>> browser.getControl(
...     name="crit__effective_FormSortCriterion:boolean").click()
>>> export_link = browser.getLink('Export')
>>> export_link.click()
>>> browser.isHtml
False
>>> print export(portal, foo_topic, layer['request'], export_link.url)
URL,Title,Description
http://nohost/plone/Members/test_user_1_/bar-document-title,Bar Document Title,blah
http://nohost/plone/Members/test_user_1_/baz-event-title,Baz Event Title,blah blah

还可以通过传递具有特殊“csv.fmtparam-”前缀的请求键来更改CSV格式。这些值作为关键字参数传递到Python的csv.writer()工厂。例如,要使用制表符作为分隔符而不是逗号,请向请求中添加“csv.fmtparam-delimiter”键。

>>> browser.open(foo_topic.absolute_url())
>>> export_url = browser.getLink('Export').url
>>> browser.open(export_url  + '&csv.fmtparam-delimiter=%09')
>>> browser.isHtml
False
>>> print export(portal, foo_topic, layer['request'],
...              export_url + '&csv.fmtparam-delimiter=%09')
URL Title   Description
http://nohost/plone/Members/test_user_1_/foo-event-title    Foo Event Title
http://nohost/plone/Members/test_user_1_/bar-document-title Bar Document Title      blah
http://nohost/plone/Members/test_user_1_/baz-event-title    Baz Event Title blah blah

还可以为没有对应目录元数据的字段添加列。请注意,使用此类列可能会大大影响性能,因为导出需要查找每个对象以检索数据。

>>> z2.login(portal.getPhysicalRoot().acl_users, testing.SITE_OWNER_NAME)
>>> text_column = columns[columns.invokeFactory(
...     type_name='TopicColumn', id='getText-column',
...     title='Text', link=True)]
>>> testing.logout()
>>> import transaction
>>> transaction.commit()
>>> browser.open(export_url)
>>> browser.isHtml
False
>>> print export(portal, foo_topic, layer['request'], export_url)
URL,Title,Description,Text
http://nohost/plone/Members/test_user_1_/foo-event-title,Foo Event Title,,<p>foo...</p>
http://nohost/plone/Members/test_user_1_/bar-document-title,Bar Document Title,blah,<p>bar...</p>
http://nohost/plone/Members/test_user_1_/baz-event-title,Baz Event Title,blah blah,

如果没有集合列,则不可用导出链接。

>>> z2.login(portal.getPhysicalRoot().acl_users, testing.SITE_OWNER_NAME)
>>> foo_topic.manage_delObjects(['columns'])
>>> testing.logout()
>>> import transaction
>>> transaction.commit()
>>> browser.open(foo_topic.absolute_url())
>>> browser.getLink('Export')
Traceback (most recent call last):
LinkNotFoundError

内容视图

可以与集合一起使用文件夹内容的一个版本,其中列是集合中“表格列”字段中指定的列。文件夹内容视图底部的按钮将应用于所选项目。

在集合的“表格列”字段中选定的任何列,如果也在“表格列链接”字段中选中,则将作为链接渲染。请注意,可以选中不是表格列的链接列,这将没有任何效果。

在“标准”选项卡上为可搜索文本索引添加简单的字符串标准。设置默认搜索词。添加排序标准以实现一致排序。

>>> from plone.app import testing
>>> from Products.CMFCore.utils import getToolByName
>>> portal = layer['portal']
>>> membership = getToolByName(portal, 'portal_membership')
>>> folder = membership.getHomeFolder(testing.TEST_USER_ID)
>>> foo_topic = folder['foo-topic-title']
>>> crit = foo_topic.getCriterion(
...     'SearchableText_FormSimpleStringCriterion')
>>> crit.setValue('bar')
>>> crit.setFormFields(['value'])
>>> sort = foo_topic.addCriterion(
...     'getPhysicalPath', 'FormSortCriterion')
>>> import transaction
>>> transaction.commit()

打开浏览器并以可以更改主题显示布局的用户身份登录。

>>> from plone.testing import z2
>>> browser = z2.Browser(layer['app'])
>>> browser.handleErrors = False
>>> browser.open(portal.absolute_url())
>>> browser.getLink('Log in').click()
>>> browser.getControl('Login Name').value = testing.TEST_USER_NAME
>>> browser.getControl(
...     'Password').value = testing.TEST_USER_PASSWORD
>>> browser.getControl('Log in').click()

将主题的显示布局和搜索表单结果布局更改为内容视图。

>>> browser.open(foo_topic.absolute_url())
>>> browser.getLink('Tabular Form').click()
>>> print browser.contents
<...
...View changed...

视图以默认列渲染内容表单。

>>> browser.getForm(name="folderContentsForm")
<zope.testbrowser.browser.Form object at ...>
>>> print browser.contents
<...
...Title...
...Size...
...Modification Date...
...State...

由于顺序由集合确定并且是固定的,因此不包括顺序列。

>>> 'Order' in browser.contents
False

主题内容以内容表单列表形式列出,标题是到项目的链接。

>>> print browser.contents
<...
...Bar Document Title...
...2.9 kB...
...<span class="state-published">Published</span>...
>>> from collective.formcriteria.testing import CONTENT_FIXTURE
>>> now = CONTENT_FIXTURE.now
>>> str(portal.restrictedTraverse('@@plone').toLocalizedTime(now)
...     ) in browser.contents
True
>>> browser.getControl('Bar Document Title')
<ItemControl name='paths:list' type='checkbox'
optionValue='/plone/Members/test_user_1_/bar-document-title'
selected=False>
>>> browser.getLink('Bar Document Title')
<Link text='Bar Document Title'
url='http://nohost/plone/Members/test_user_1_/bar-document-title'>

第一个排序标准是默认排序。

>>> browser.getControl(name="sort_on").value
'sortable_title'

选择不同的集合列和链接到结果项的列。

>>> z2.login(portal.getPhysicalRoot().acl_users, testing.SITE_OWNER_NAME)
>>> columns = foo_topic.columns
>>> columns.manage_delObjects(
...     ['ModificationDate-column', 'get_size-column',
...      'review_state-column'])
>>> columns['Title-column'].update(link=False)
>>> desc_column = columns[columns.invokeFactory(
...     type_name='TopicColumn', id='Description-column',
...     link=True)]
>>> effective_column = columns[columns.invokeFactory(
...     type_name='TopicColumn', id='EffectiveDate-column',
...     link=True)]
>>> foo_topic.manage_delObjects(
...     ['crit__get_size_FormSortCriterion',
...      'crit__get_size_FormSimpleIntCriterion',
...      'crit__modified_FormSortCriterion',
...      'crit__modified_FormDateCriterion',
...      'crit__review_state_FormSortCriterion',
...      'crit__review_state_FormSelectionCriterion'])
>>> testing.logout()
>>> import transaction
>>> transaction.commit()

视图以指定的列渲染内容表单。

>>> browser.open(foo_topic.absolute_url())
>>> browser.getForm(name="folderContentsForm")
<zope.testbrowser.browser.Form object at ...>
>>> print browser.contents
<...
...Description...
...Effective Date...
...Title...
>>> 'Size' in browser.contents
False
>>> 'Modification Date' in browser.contents
False
>>> '&#160;State&#160;' in browser.contents
False

主题内容也以指定的列列出。

>>> print browser.contents
<...
...Bar Document Title...
...blah...
>>> '2.9 kB' in browser.contents
False
>>> now.ISO() in browser.contents
False
>>> '<span class="state-published">Published</span>' in browser.contents
False

链接列也已更改。

>>> browser.getControl('Bar Document Title')
<ItemControl name='paths:list' type='checkbox'
optionValue='/plone/Members/test_user_1_/bar-document-title'
selected=False>
>>> browser.getLink('blah')
<Link text='blah'
url='http://nohost/plone/Members/test_user_1_/bar-document-title'>
>>> browser.getLink((now-2).ISO())
<Link text='...'
url='http://nohost/plone/Members/test_user_1_/bar-document-title'>
>>> browser.getLink('Bar Document Title')
Traceback (most recent call last):
LinkNotFoundError

项目选择标题行反映了新的列数。

>>> print browser.contents
<...
...<thead>...
...<th colspan="4"...
...</thead>...

KSS更新表视图也反映了所选列。

>>> browser.open(
...     foo_topic.absolute_url()+'/foldercontents_update_table')
>>> print browser.contents
<...
...Description...
...Effective Date...
...Title...
>>> 'Size' in browser.contents
False
>>> 'Modification Date' in browser.contents
False
>>> '&#160;State&#160;' in browser.contents
False

查询条件

如果查询标准已分配给特定列,则将在筛选表标题行中渲染。否则,它们将像往常一样在搜索表单中渲染。

添加组件。

>>> from zope import component
>>> from plone.i18n.normalizer import (
...     interfaces as normalizer_ifaces)
>>> from collective.formcriteria.portlet import portlet
>>> testing.login(portal, testing.TEST_USER_NAME)
>>> manager = foo_topic.restrictedTraverse(
...     '++contextportlets++plone.rightcolumn')
>>> site_path_len = len(portal.getPhysicalPath())
>>> assignment = portlet.Assignment(
...     header='Foo Search Form Title',
...     target_collection='/'.join(
...         foo_topic.getPhysicalPath()[site_path_len:]))
>>> name = component.getUtility(
...     normalizer_ifaces.IIDNormalizer).normalize(
...         assignment.title)
>>> manager[name] = assignment
>>> testing.logout()

如果为表格列配置了查询标准,则将渲染筛选表标题行作为搜索表单。

>>> foo_topic.setFormLayout('folder_contents')
>>> import transaction
>>> transaction.commit()
>>> browser.open(foo_topic.absolute_url())
>>> contents_form = browser.getForm(name="folderContentsForm")
>>> contents_form.getControl(
...     name='form_crit__SearchableText_FormSimpleStringCriterion'
...     '_value', index=0)
<Control
name='form_crit__SearchableText_FormSimpleStringCriterion_value'
type='text'>
>>> contents_form.getControl(
...     name='form_crit__Title_FormSimpleStringCriterion_value',
...     index=0)
<Control
name='form_crit__Title_FormSimpleStringCriterion_value'
type='text'>
>>> contents_form.getControl('Filter', index=0)
<SubmitControl name='filter' type='submit'>

由于所有查询标准都用于表格列,因此不会渲染组件搜索表单。

>>> browser.getForm(name="formcriteria_search")
Traceback (most recent call last):
LookupError

内容视图反映了通过内容表单提交的用户标准。

>>> contents_form.getControl(
...     name='form_crit__SearchableText_FormSimpleStringCriterion'
...     '_value', index=0).value = 'baz'
>>> contents_form.getControl('Filter', index=0).click()
>>> browser.getControl('Bar Document Title')
Traceback (most recent call last):
LookupError: label 'Bar Document Title'
>>> browser.getControl('Baz Event Title')
<ItemControl name='paths:list' type='checkbox'
optionValue='/plone/Members/test_user_1_/baz-event-title'
selected=False>

单击搜索文本框时,筛选可折叠不会折叠。

>>> import re
>>> regexp = re.compile('http://.*?collapsiblesections.css')
>>> regexp.search(browser.contents).group()
'http://nohost/plone/portal_css/Plone%20Default/collapsiblesections.css'
>>> browser.open(portal.absolute_url() + '/collapsiblesections.css')
>>> print browser.contents
/*...
#foldercontents-getPath-filter .collapsibleHeader {
...

如果存在未分配给列的查询标准,则将渲染搜索表单。

>>> z2.login(portal.getPhysicalRoot().acl_users, testing.SITE_OWNER_NAME)
>>> columns['getPath-column'].update(filter='')
>>> testing.logout()
>>> import transaction
>>> transaction.commit()
>>> browser.open(foo_topic.absolute_url())
>>> portlet_form = browser.getForm(name="formcriteria_search")

内容视图也反映了通过组件表单提交的用户标准。

>>> portlet_form.getControl(
...     name='form_crit__SearchableText_FormSimpleStringCriterion'
...     '_value').value = 'baz'
>>> portlet_form.getControl(name='submit').click()
>>> browser.getControl('Bar Document Title')
Traceback (most recent call last):
LookupError: label 'Bar Document Title'
>>> browser.getControl('Baz Event Title')
<ItemControl name='paths:list' type='checkbox'
optionValue='/plone/Members/test_user_1_/baz-event-title'
selected=False>

如果没有配置查询标准,则不会渲染筛选表标题行。

>>> z2.login(portal.getPhysicalRoot().acl_users, testing.SITE_OWNER_NAME)
>>> columns['Title-column'].update(filter='')
>>> testing.logout()
>>> import transaction
>>> transaction.commit()
>>> browser.open(foo_topic.absolute_url())
>>> print browser.contents
<...
      <thead...
        <tr>
            <th class="nosort"...>&#160;</th>
            <th class="nosort sortColumn"
                id="foldercontents-sortable_title-column">
                  &#160;
                  Title
                  &#160;
                </th>
            <th class="nosort noSortColumn"
                id="foldercontents-Description-column">
                  &#160;
                  Description
                  &#160;
                </th>
            <th class="nosort noSortColumn"
                id="foldercontents-EffectiveDate-column">
                  &#160;
                  Effective Date
                  &#160;
                </th>
        </tr>
      </thead...
      <tbody...

链接到项目的单元格只有一个链接,没有图标。如果包含特殊的“路径”列,则将显示图标。

>>> print browser.contents
<...
              <td class="notDraggable">
                  <input type="checkbox" class="noborder" name="paths:list" id="cb_-plone-Members-test_user_1_-bar-document-title" value="/plone/Members/test_user_1_/bar-document-title" alt="Select Bar Document Title" title="Select Bar Document Title" />
                  <input type="hidden" name="selected_obj_paths:list" value="/plone/Members/test_user_1_/bar-document-title" />
                  <label for="cb_-plone-Members-test_user_1_-bar-document-title">
                    <span class="contenttype-document">
...
                    </span>
                    <span class="hiddenStructure">Bar Document Title</span>
                  </label>
              </td>
...
                    <span class="contenttype-document">
                      <a href="http://nohost/plone/Members/test_user_1_/bar-document-title"...
                        blah
                      </a>
                    </span>
...

更新日志

2.1 (2016-08-05)

  • 添加travis构建脚本[bogdangi]

  • 修复表单视图和表单标准编辑中的标题和描述问题[bogdangi]

  • 添加了进一步的Plone 4.3兼容性[miohtama]

  • 在表单中使用现有的i18n消息ID。[icemac]

2.0 - 2012-11-01

  • Plone 4.2和4.3兼容性。[rossp]

  • 使用本地化格式为DateTime列值。[rossp]

  • 为路径条件中的递归字段添加缺失的表单条件支持。 [rossp]

  • 限制一些搜索表单小部件的支持,使其仅在正常Plone视图的左右列小部件管理器以及仪表板视图的4个仪表板小部件管理器上运行,出于性能考虑。这意味着如果您想在不受这些注册影响的管理器中使用搜索表单小部件,您必须使用自己的注册,如collective/formcriteria/form/configure.zcml中的<browser:viewlet>注册。 [rossp]

  • 更新chameleon兼容性到新的2.x分支。 [rossp]

  • 优化并提高性能。 [rossp]

  • 各种上游模板更新。 [rossp, topherh]

  • 为folder_summary_view添加远程URL支持。 [topherh]

  • 修复保护导出操作的权限问题。 [rossp]

  • 优雅地处理目录索引ParseErrors。感谢Larry Pitcher的报告。 [rossp]

2.0b2 - 2011-01-13

  • 添加一些Plone 3兼容性。Plone 3在版本2+中不受支持。测试通过,但UI尚未检查,所以YMMV。 [rossp]

2.0b1 - 2011-01-11

  • 添加了管理集合列的基本UI。 [rossp]

2.0a4 - 2011-01-11

  • 恢复缺失的从主题文件夹内容视图中的工作流菜单。感谢Larry Pitcher的报告。 [rossp]

2.0a3 - 2011-01-10

  • 更改分组列表视图的权限,以便匿名访客在内容发布时可以访问视图。感谢Larry Pitcher的报告。 [rossp]

  • 添加对没有对应目录元数据的列的支持。请注意,使用此类列可能会极大地影响性能,因为导出需要查找每个对象以检索数据。 [rossp]

2.0a2 - 2010-11-23

  • 修复了关于FormDateCriterion中DateTimeFields的错误类型假设的问题。实际上FormDateCriterion并没有使用DateTimeField。 [rossp]

  • 重构基于<form>和<button>的批宏,以避免与现有表单中完整“导航”宏的其他使用冲突,导致嵌套的<form>。 [rossp]

2.0a1 - 2010-11-21

  • 确保通过默认方式使用“default”配置文件,即通过portal_quickinstaller。嗯,默认。 :-) [rossp]

  • 在导航/分页批宏中使用<form>和<button>元素,以防止使用许多表单条件进行分页时出现“uri too long”错误。 [rossp]

  • 对于大量表单条件的使用,使用method="post"来解决“uri too long”问题。由mauro报告,并确认仅在两个日期字段的情况下发生。 [rossp]

  • 在文件夹列表皮肤模板中添加Plone4兼容性的定义。 [seletz]

  • 修复navigation_recurse模板,以匹配当前的Plone 4版本。 [seletz] [ramonski]

  • 添加一个使用文件夹列表宏进行丰富小部件的集合列表小部件。 [rossp]

  • 修复在添加路径条件时产生 AttributeError: ‘NoneType’ object has no attribute ‘title_or_id’ 的问题。 [hplocher]

  • 修复了‘<input type="hidden" name="sort_on"…’,现在如果存在则使用默认排序条件

  • 使用单个持久对象表示表格列,例如使用folder_contents视图。尚未实现编辑folder_contents列对象的UI。

  • 修复<tfoot>的使用 [rossp]

  • 将排序条件与文件夹内容视图列集成以实现KSS排序 [rossp]

  • 添加基于FormSelectionCriterion、FormPortalTypeCriterion和FormReferenceCriterion的单值下拉/选择列 [rossp]

1.1.1 - 2009-08-31

  • 文件夹内容视图中的“全选”和“显示全部”(KSS) [rossp]

1.1.0 - 2009-08-21

  • 使用folder_contents而不是folder_contents_view来修复指向文件夹内容表单的链接。 [rossp]

  • 调整搜索表单小部件的间距。 [rossp]

  • 使用“表格列”字段来控制文件夹内容表单的文件夹内容列

  • 使用“表格列链接”集合字段来指定哪些文件夹内容表单列应链接到项目 [rossp]

  • 修复文件夹内容按钮,"复制"、"剪切"、"重命名"、"更改状态"和"删除"现在都可以针对由集合列出的对象工作,即使它们位于不同的文件夹中。[rossp]

1.0.2 - 2009-08-12

  • 添加一些缺失的 portal_types 以满足条件。[rossp]

  • 修复了搜索插件的 GS portlets.xml 导入中的 Unicode 错误。[rossp]

1.0.1 - 2009-08-11

  • 合并 collective.catalogexport 以支持基于用户提交查询的集合 CSV 导出。[rossp]

1.0 - 2009-04-20

  • 确保只从请求中获取 formFields

  • 修复了被 SimO 报告的忽略整数范围条件。[rossp]

  • 使用浏览器层(由 optilude 建议)

  • 为批量宏排序链接添加 ids 和 CSS 类(aaronv)

  • 修复了“操作符”字段的问题。感谢 Mauro!

0.9.5 - 2009-03-06

  • 将包移动到 src 目录并修复测试 buildout

  • 使用正确的包名注册 criteria AT 类型

  • 修复了通过索引/字段缩小 criteria 类型的 JavaScript 错误。

  • 使用单独的 meta_types 而不是覆盖 ATCT meta_types,可能对以前的安装不兼容

0.9.4 - 2009-02-08

  • 添加一个按使用的排序分组项的布局

  • 修复了 jonstahl 报告的 KeyError: u'unsorted' 错误。

0.9.3 - 2009-01-31

  • 修复了搜索表单插件的 widget JavaScript 和 CSS。

0.9.2 - 2009-01-31

  • 阐明选择的排序

  • 使插件在集合上下文之外也可用

  • 修复了插件类

  • 不在日期上渲染小时和分钟字段

0.9.1 - 2009-01-30

  • 将搜索表单视口移动到插件中

  • 修复了 ATCT addCrierion 方法以正确初始化 criteria,以便它们可以在代码中安全创建。

  • 使用与 FormDateCriterion 相同的不匹配的 meta_type ATCT

0.9 - 2009-01-29

  • 修复了向现有的 ATCT ATTopic 实例添加扩展排序条件时的不兼容性。

0.8 - 2009-01-29

  • 在批量宏中添加多个排序链接

0.7 - 2009-01-28

  • 在适当的情况下使用与 ATCT 相同的名称以避免一些问题,其中期望 ATCT 名称。

  • 完善 GenericSetup 配置文件,包含 Plone 配置文件中引用 criteria 的所有其他部分。

0.6 - 2009-01-26

  • 为搜索表单使用表单前缀。修复了日历 JavaScript 错误。

  • 修复 criterion 标签以指向正确的表单输入

  • 允许即使标签未渲染,也显示 widget 特殊帮助/描述,并为此使用逗号控件

  • 修复了逗号控件中 postbacks 的处理

  • 使用仅渲染搜索表单的“搜索表单”视图

  • 添加布尔 criteria

  • 添加日期 criteria

  • 添加路径 criteria

  • 添加相对路径 criteria

  • 添加整数 criteria

0.5 - 2009-01-25

  • 通过选择每个 criteria 应在搜索表单上渲染哪些字段来指定 form criteria

  • 改进标签处理。移除“值”字段的标签和所有字段的“必需”标记。

  • 使搜索表单可折叠,并在表单提交时开始折叠

  • 添加逗号分隔的 criterion

0.4 - 2009-01-15

  • 添加列表 criterion

  • 添加选择 criterion

  • 修复了匿名用户访问表单的问题

0.3 - 2009-01-15

  • 完全重用 AT 编辑控件

  • 支持具有多个字段的 criteria

  • 使用控件处理表单值

  • 基于 FormSelectionCriterion、FormPortalTypeCriterion 和 FormReferenceCriterion 添加复选框 criterion

  • 添加日期范围表单 criterion(JS 日历尚未工作)

0.2 - 2008-05-27

  • 修复 ZCML 中的 i18n_domain

  • 使认证器视图对 Plone 3.0 兼容性条件化

0.1 - 2008-05-24

  • 初始发布

待办事项

  • 用 jQuery 替换 KSS 以处理 AJAX 文件夹内容。

  • 为主题容器(如主题列)等文件夹内容基于的多对象编辑表单添加选项卡。

  • 将查询和排序 criteria 分离到主题容器中,并使用文件夹内容基于的多编辑表单。

  • 在使用KSS选择所有屏幕时添加对文件夹内容按钮的覆盖。对于一次部署不起作用。

  • 为可排序的文件夹内容列添加排序图标

  • 支持在CSV导出中包含URL

    不确定正确的UI是什么,也许可以将特殊案例添加到customViewFields字段中。

  • 添加条件排序支持

  • 表单排序条件

    有一个小部件用于选择哪些可能的排序字段可用于排序。使用InAndOutWidget以确保可以指定顺序。

    >>> print browser.contents
    <...
    <div class="field ArchetypesInAndOutWidget
    kssattr-atfieldname-sortFields"
    id="archetypes-fieldname-sortFields">...
    ...>Relevance</option>...
    ...>Effective Date</option>...
    

    InAndOutWidget使用JavaScript,因此我们将手动设置字段进行测试。

    >>> self.login()
    >>> foo_topic.setSortFields(['', 'effective', 'Type'])
    
    >>> form = browser.getForm(name="criteria_select")
    >>> form.getControl('Sort Order').selected = True
    

    表单排序条件默认按“相关性”字段排序,对应于包含对支持加权结果的索引的查询的搜索中的按权重排序。

    >>> form = browser.getForm(action="criterion_edit_form", index=0)
    >>> form.getControl('Relevance').selected
    True
    
  • 添加AJAX搜索结果刷新

  • 添加单选选择(下拉列表,单选按钮)条件(davisagli)

  • 使用子集合来支持高级查询操作

    集合将作为分组/括号 操作符。换句话说,集合将有一个布尔字段来设置是否使用AND或OR来找到其结果集的交集或并集。子集合不会获取条件,而是父集合将子集合视为条件分组。尚未确定如何处理排序。

项目详情


下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分布

collective.formcriteria-2.1.tar.gz (104.2 kB 查看哈希值)

上传时间

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面