Wikidot数据表单系统参考手册

模块暂不可用: 此动态功能尚未由只读迁移站支持。

[[embed]]
<iframe src="//interwiki.scpwikicn.com/styleFrame.html?priority=2
&type=sidebar
&override={$override}&theme=https://cdn.scpwiki.com/theme/en/basalt/normalize-min.css
&css={$css}" style="display: none"></iframe>
[[/embed]]

[[embed]]
<iframe src="//interwiki.scpwikicn.com/styleFrame.html?priority=2
&type=sidebar
&override={$override}&theme=https://oxygennine.github.io/Peroxide/CSS/Interwiki/Interwiki.css
&css={$css}" style="display: none"></iframe>
[[/embed]]

隐藏Saving Pages显示Saving Pages
Rating: +82

数据表单(Data forms)是Wikidot最强大的功能之一,但对于大部分写作网站而言,一般的创作者并不需要用到这个功能。不过,在需要将数据结构化处理时(例如,在组队竞赛中填报队伍信息、上传特定格式的实验记录等),表单功能将变得非常实用。本文参考Wikidot的官方文档,将全面讲解表单系统的使用方法和应用场景。

创建表单

建立模板页面

简单来说,我们必须为一个表单系统建立一个专属分类。例如,假设我们将开办一场组队进行的征文竞赛“2026填表竞赛”,需要参赛队伍按格式上传信息并集中在中心页展示,那么第一步应该是建立formcon2026:_template这个页面。

_template是页面分类的专属模板页面,在模板页的修改会被自动同步至这个分类下的所有页面。这也意味着_template最好被管理员锁定以免遭受恶意破坏。

formcon2026:_template中,使用[[form]]…[[/form]]就可以自动将整个分类转化为数据表单分类。这也意味着,不能在同一个分类中混合存放数据表单页面和普通维基页面。每个数据表单页面都属于某个特定分类下的单独页面。一个分类仅能设置一个数据表单,且该表单结构会应用到该分类下的所有页面。

设置数据结构

{{@@[[form]]…[[/form]]@@}}的内容类似[*https://www.runoob.com/w3cnote/yaml-intro.html YAML]。

YAML语法教程

+ 展开这部分- 收起这部分

YAML是一种极度简洁的标记语言,用来描述有层级的数据。它的特点是:

  • 使用空格数量来表示缩进层级,不使用缩进符(Tab)。空格的数量不重要,但一定要是最低一层的整倍数(例如,2、4、6个空格,或者3、6、9个空格都可以表示1、2、3级)。
  • 使用key: value来描述键和值,冒号后必须有空格。
  • 大小写敏感。

没了。实际上,这就是Wikidot表单系统用到的YAML的全部了。

下面是一个简单的示例:



[[form]]

fields:
  teamName:
    label: 队伍名称
    type: text
    width: 30
  teamNumber:
    label: 人数
    type: select
    values:
      1: 1
      2: 2
      3: 3
      4: 4
      5: 5
  teamBoss:
    label: 队长
    type: text
    width: 30
  ifTeamNewbee:
    label: 是否为新人队伍
    type: checkbox
    default: 1
  teamLogo:
    type: file
    label: 上传LOGO图片
    category: formcon2026-files

[[/form]]

formcon2026这个分类下创建任何页面时,原来的编辑框会消失,代之以这样的、可填写的表格:

69f4b2ae209b4.png

表格分为左侧列右侧列。通常情况下,左侧列是需要填写的字段名称,右侧列是等待填写或选择的值。

对包含数据表单的类别启用自动编号可以消除页面名称重复的风险。此设置在站点管理器的“页面自动编号”功能中完成。

我们以此为例解释formcon2026:_template的内容。

字段

fields是开头的根字段,要被Wikidot识别,YAML必须有且只能有唯一一个fields顶级字段。在fields下,有一个或多个子字段,每个字段共有的属性包括:

  • label:用户在表单中看到的字段名称。随意填写字符串。
  • type:字段类型。需要选择一个关键字(见后文)。
  • [property]:根据字段类型定义的属性。

例如在

fields:
  teamName:
    label: 队伍名称
    type: text
    width: 30

这个表单中,fields下有一个名为teamName的字段,它显示为“队伍名称”(见上图),类型是text(用户输入字符串),还有一个叫width的属性,属性的值是30,意味着这个输入框的长度是30。

适用于所有字段类型的属性

label

如果你指定了label属性,则该字段在左侧列中显示label属性的值,或对于合并字段则显示在字段之前。如果你未指定label,则该字段在左侧列中留空,或对于合并字段则紧贴在前一个字段之后。

join

如果你指定了join: true,则该字段会被放置在前一个字段的右侧列(如果存在前一个字段)。如果该字段是表单中的第一个字段,则此属性无效。例如:

  city:
    label: City
    width: 20
  postcode:
    label: Postcode
    width: 8
    join: true

6a65e7a70bf5e.png

在这个例子中,postcode表现为city的一个子属性。

before和after

before提供一段纯文本字符串,显示在字段值之前。after提供一段纯文本字符串,显示在字段值之后。

  phone:
    label: 电话号码
    width: 10
    before: +(86)
  price:
    label: 竞赛奖金
    width: 10
    after: 元

6a65e9586fe6e.png

字段类型(type)可选的值

text

定义文本或文本框字段。如果某个字段不指定type,则默认是这个类型的字段。允许使用widthheight作为属性。如果不指定高度,则为普通的单行文本字段;如果指定高度,则为文本框。Wiki语法在文本字段中无效。

可在文本字段上使用的具体属性:
width: 指定可见字段宽度(以列数计,大致为固定间距字符数)。
height: 指定字段高度(以行数计),1为普通文本字段,2或以上为文本框。
match: 指定字段值必须匹配的正则表达式。
match-error: 指定自定义错误信息。
hint: 提供字段为空时显示的提示文本。如需使用像#这样的特殊字符,需要使用\进行转义。
default: 定义新页面上显示的字段默认值。需注意,default在大部分字段中都可以使用。

  name:
    label: 名字
    type: text
    width: 30
    default: 小明
  comment:
    label: 评论
    type: text
    width: 50
    height: 3
    hint: 这里是评论区,不是无人区~
  email:
    label: 邮件地址
    match: /^[_a-zA-Z0-9\-\+]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+$/
    match-error: 邮件格式错误!

6a65ed015d405.png

wiki

text类似,但是wiki允许用户输入维基语法。

select

定义一个多值选择字段。需要一组值。如果指定两到四个值,则会得到水平单选字段。如果指定五个或更多值,则会得到下拉选择字段。例如:

  gender:
    label: 性别
    type: select
    values:
      0: 男
      1: 女
      2: 其他
      3: 保密
  type:
    label: 喜欢的音乐种类
    type: select
    values:
      0: 古典
      1: 乡村
      2: 民谣
      3: 独立
      4: 爵士
      5: 流行
      6: 摇滚
    default: 6

6a65ed2e74f6a.png

在上述示例中,选择字段的属性为0到6,默认属性为6,将值设置为摇滚。不过,您也可以使用字符串作为属性,例如

cl: 古典
co: 乡村
fk: 民谣
in: 独立
jz: 爵士
po: 流行
ro: 摇滚

注意:YesNoTrueFalse的值是保留值,在驱动数据表单的YAML代码中具有特殊含义。要在数据表单中使用它们,需要将它们放在引号内,否则将无法正常工作。

  done:
    label: 是否完成?
    type: select
    values:
      not: "No"
      done: "Yes"
    default: not

checkbox

checkbox定义一个复选框字段,在表单数据中存储为0或1。

  onions:
    label: 你喜欢洋葱吗?
    type: checkbox
    default: 1

6a65ee5b8df6e.png

pagepath

pagepath允许用户创建并在页面树中的某个页面内进行选择;“路径”指的是所有父级页面加上该页面本身的列表。它以“页面 / 页面 / 页面 / 页面”的形式可视化呈现,每个层级都提供查看该页面、更换页面或添加新子页面的选项。这不会影响实际的页面父级关系,且一个表单可以包含多个页面路径字段。页面路径字段的值以页面的完整名称形式存储。隐藏页面在用户选择和浏览页面树时不可见。

  • category:指定包含页面树的页面分类。
  • default:定义新页面上显示的字段的默认值。
  • max-level:设置可在页面路径树中创建的最大层级数。

hidden

向表单添加用户无法看到或编辑的数据。它在视觉上不占用任何空间。这是为了将数据放入页面,以便以后可以使用这些数据。该字段的值由value属性定义。例如,下面的例子让表单有一个值为1.0的隐藏字段,字段名为version

  version:
    type: hidden
    value: 1.0

static

static显示为不可编辑文本,并允许表单设计者为表单添加文本和格式。static字段不会存储在页面中,值来自value属性。value可以使用大多数wiki语法,并且可以通过在开头添加一个竖线符号|,然后在接下来的内容保持缩进的方式构建连续的换行。value的所有内容都无需转义符号。

  header-1:
    type: static
    label: 'Inline Formatting Docs'
    value: |
             //italic text//    italic text
             ||~ what you type ||~ what you get ||
             || {{@@//italic text//@@}} || //italic text// ||
             || {{@@**bold text**@@}} || **bold text** ||
             || {{@@//**italic and bold**//@@}} || //**italic and bold**// ||
             || {{@@__underline text__@@}} || __underline text__ ||
             || {{@@--strikethrough text--@@}} || --strikethrough text-- ||
             || {{@@{{teletype (monospaced) text}}@@}} || {{teletype (monospaced) text}} ||
             || {{@@normal^^superscript^^@@}} || normal^^superscript^^ ||
             || {{@@normal,,subscript,,@@}} || normal,,subscript,, ||
             || {{@@[!-- invisible comment --]@@}} || [!-- invisible comment --] ||
             || {{@@[[span style="color:red"]]custom //span// element[[/span]]@@}} || [[span style="color:red"]]custom //span// element[[/span]] ||
             || {{@@##blue|predefined## or ##44FF88|custom-code## color@@}} || ##blue|predefined## or ##229966|custom-code## color ||

             [[div class="alert alert-info"]]
             You can use user-defined {{ID}} arguments in **@@[[span]]…[[/span]]@@** tags, which is extremely useful building sites using [http://getbootstrap.com Bootstrap]. Please note that every user-defined {{ID}} will have a {{"u-"}} prefix added in the output HTML for the security reasons.
             [[/div]]

6a66206e0a773.png

相同的代码也可以通过将整个字符串包裹在双引号中,并使用\n作为转义换行符来实现。

file

这允许用户直接从数据表单上传文件,并显示为文件的链接。

注意:文件不会上传到同一页面。相反,每个文件会在给定的页面分类(默认为“files”)中单独创建一个页面,页面名称为该附件的名称。通过指定category属性,可以指定页面创建时所处的页面类别,上传的文件将附加到此页面。在此示例中,每上传一个附件,就会在formcon2026-files这个页面分类下新开一个页面。

  teamLogo:
    type: file
    label: 上传LOGO图片
    category: formcon2026-files

6a6621a6e62fd.png

若要展示图片,必须使用%%form_raw{字段名称}%%而非%%form_data{字段名称}%%来显示图片链接,然后嵌入到维基语法例如[[image]]中。

如果在数据表单的文件字段中没有上传图片,一些浏览器会显示错误标识。这看起来不美观,容易让人觉得操作有误。因此,您可以改为显示一张默认图片作为替代。这张图片可以是空白图像,也可以是与网站相关的通用图像。如果在数据表单的该字段中上传了图片,则会使用上传的图片进行展示。在上面的“2026填表竞赛”中,为团队LOGO设置默认值的CSS示例如下:

css
[[module CSS]]
.form-image-default%%form_raw{teamLogo}%%{ display: block !important; }
.form-image%%form_raw{teamLogo}%%{ display: none !important; }
[[/module]]
[[div class="form-image"]]
[[image %%form_raw{teamLogo}%%]]
[[/div]]
[[div class="form-image-default" style="display: none;"]]
[[image <默认logoURL>]]
[[/div]]

url

让用户输入URL。该内容将以链接形式显示。可在此字段上使用的具体属性:

  • default:定义新页面上显示的字段默认值。
  • default-schema:为URL定义默认协议(如未指定,默认为{{http://}})。
  • match-error:指定自定义错误信息。
  • required:指定该字段是否为必填项[true/false](如未指定,默认为false)。

password

允许用户输入“密码”——对用户而言,他们输入的每个字符都会被替换为星号。注意:保存页面后,密码以明文形式储存在源代码中,任何人都可以查看,没有任何加密措施。

这TM到底是要干嘛,搭钓鱼网站吗??

date

定义一个日期输入字段,使用jQuery UI日期选择器小部件来选择日期。可以使用options选项指定jQuery UI Datepicker Widget选项。例如:

  • showon: button:在输入字段后添加一个按钮,必须点击该按钮才能打开日期选择器。
  • autoSize: true 自动设置输入框的宽度,以适配dateFormat选项中定义的日期格式。
  • changeYear: true:创建一个年份下拉选择器。如果你不希望用户点击上一年/下一年链接12次才能切换到其他年份,此功能非常有用。
  • dateFormat: 'DD, d MM yy':将所选日期格式化为类似"Wednesday, 1 October 2014"的形式。
  • firstDay: 1:告知日历将星期一作为小部件日历中每周的第一天,而非默认的星期日(0=星期日,1=星期一,……,6=星期六)。
  • yearRange: '2026:2027':将年份选择限制在指定范围内。
  mydate:
    type: date
    label: '日期'
    options:
      appendText: '请输入文本'
      autoSize: true
      changeYear: true
      dateFormat: 'DD, d MM yy'
      firstDay: 1
      showOn: button
      yearRange: '2026:2027'

6a66253a1d2d0.png

日期字段中的日期以数字形式存储,并根据你指定的dateFormat选项进行显示。添加altFormat选项可为备用日期使用不同的日期格式。如果你想将日期保存为文本而非数字,可以使用altField选项将日期的文本版本放入数据表单的另一个字段中。有关此字段的完整说明见官方文档

展示表单

格式化表单页面

如果你只保存[[form]]..[[/form]]结构,然后创建页面,每个页面都会有一个简单布局,每个字段按表单结构的顺序依次排列在前一个字段下方。在这种简单布局下,上传的图片也不会显示,只会显示一个图片链接。但你可以按照自己的喜好来布置显示的字段,并展示上传的图片和视频。为此,你需要将_template页面分成两个区域,中间用=====分隔符隔开。=====上方的内容可以随意设置,然后使用以下占位符表示表单内容:

  • %%form_data{字段名称}%%:显示所选字段的内容。除URL(图像、视频、电子邮件等)外,几乎所有内容均使用此变量。
  • %%form_raw{字段名称}%%:显示所选字段的未格式化内容。用于URL信息(图像、视频等)以及需要高级Wikidot语法(包含、模块)的情况。
  • %%form_label{字段名称}%%:显示字段label属性(如果有的话)。
  • %%form_hint{字段名称}%%:显示字段的hint属性(如果有的话)。

以上面的“2026填表竞赛”为例,如果开头改成这样:

+ %%form_data{teamName}%%

你们是一个**%%form_data{teamNumber}%%**人的队伍。

[[#ifexpr %%form_raw{ifTeamNewbee}%%>0 | 你们是新人队伍。 | 你们不是新人队伍。]]

= 队长:[[*user %%form_data{teamBoss}%%]]

=====

[[form]]

fields:
…

在提交表单后,每个表单页面就会呈现为类似这样的状态:

6a662a0907baa.png

注意,ifTeamNewbee是复选框字段,所以勾选时值是1,不勾选就是0。这里先提取原数据,然后判断它是否大于0,展示对应的文本。

使用ListPages模块调取表单数据库内容

数据表单产生的数据可用于ListPages模块,详细用法参考Wikidot模块参考手册。它使用和上面完全一致的占位符。下面是一个创建所有参赛队伍的表格的示例。

[[module ListPages category="formcon2026" order="name"  separate="false" prependLine="||~ 队伍名||~ 是否为新人队伍 ||~ 人数 ||" appendLine="||||||||~ ||"]]
|| %%title_linked%% || [[#ifexpr %%form_raw{ifTeamNewbee}%%>0 | 是 | 否]] || %%form_data{teamNumber}%% ||
[[/module]]

在ListPages模块中,页面选择参数_<data-form-field-name>可以选择某个字段有特定值的页面。例如,要列出所有新人参赛队伍,请使用下划线开头的参数_ifTeamNewbee="1"。任何表单系统的字段名都可以用作ListPages模块的自定义参数名,下面给出筛选所有新人队伍且非独立参赛的队伍名单的示例:

[[module ListPages _ifTeamNewbee="1" _teamNumber=">1"]]

若要按照某个字段的值排序,使用order="_<data-form-field-name>",例如order="_teamNumber desc"注意:为了使排序正常工作,低于10的数字必须具有01、02、03等属性,尽管值仍然可以是1、2、3等,如下方的示例数据表单字段所示。在ListPages模块中显示的是正常的1、2、3等。由于01, 02, 03, …被视为八进制数字,您需要用分号将它们括起来("01", "02", "03", …),因为八进制中没有08和09,它们都会变成0。

 albums:
    label: Albums/CDs released
    type: select
    values:
      "00": 0
      "01": 1
      "02": 2
      "03": 3
      "04": 4
      "05": 5
      "06": 6
      "07": 7
      "08": 8
      "09": 9

标签

目前无法在保存数据表单时根据表单中的值设置标签。但在标签字段实现之前,有一种变通方法可行:使用[[button set-tags]]。这是Wikidot提供的半自动为页面设置标签的方式,通过在_template页面添加类似{{@@[[button set-tags -* +%%form_raw{字段名称1}%% +%%form_raw{字段名称2}%% …]]@@}}的方式,可以让用户按下一个按钮,自动为页面添加他选择的字段对应的标签。相关讨论见[*http://community.wikidot.com/forum/t-402555/automatically-setting-tags-for-a-page-based-on-form-input 此处]。

相较于纯ListPages方案

许多竞赛和活动需要处理结构化的数据。例如,2026年部门毁灭竞赛的机制是这样的:通过在fragment分类建立格式化的页面,用户复制一个纯文本模板,并修改内容,用ListPages提取不同段落,再将内容注入中心页。这样做至少存在几个隐患:(1)Wikidot的ListPages模块现在已经出现明显的延迟,从几分钟到一小时甚至更长;(2)ListPages提取段落严格依赖于特定的格式,稍有错误就可能让中心页的排版产生严重混乱,甚至无法访问;(3)编辑界面不直观,严重依赖于注释说明。

在这方面,表单系统和ListPages的混合方案是纯ListPages的完美平替。表单系统目前仍然保持零延迟,任何改动都可以实时响应;由于可以使用无视维基语法的text纯文本字段,中心页排版不会被意外破坏,甚至可以防御恶意攻击;表单填写界面是自动生成的表格,所有位置一目了然。实际上,表单系统的本质是把作品和作品相关数据解耦合,这意味着它提供了设计机制更复杂的竞赛的可能性,例如:

  • 通过提前注册表单实现随机用户/作品池;
  • 在类似2026家具城,通过场外计算分数的基础上,在维基页面内实现按照场外分数排名;
  • 在类似2026部门毁灭竞赛的基础上,直接在页面内上传附件;
  • 在类似电子游戏竞赛的基础上,通过表单系统提供快速管理报名队伍的方式;
  • ……

表单系统是Wikidot开放给每个人的数据库管理系统,但目前对它的功能开发远不如ListPages、CSS技巧等其它方面的内容深入。笔者乐意看到更多基于表单系统的、Wikidot特有的“戴着镣铐跳舞”式功能实现。

另请参见:

页面版本:⁨0⁩, 最后编辑于: ⁨2026/7/26 16:34:59⁩ (⁨⁨52⁩ 日前⁩), 现时评分: 82