oTree学习教程(五Forms

oTree中的每个页面都可以包含一个表单,玩家应通过单击“下一步”按钮填写并提交该表单。要创建表单,首先需要Player在models.py中的类中使用字段。然后,在您的Page类中,设置form_modelform_fields

例如,这是models.py:

和pages.py:

当用户提交表单时,提交的数据将自动保存到玩家模型上的相应字段中。

(您也可以设置form_model ='group'而不是player;请参阅form_model ='group'。)

在2018年1月,语法从form_model = models.Player更改为form_model ='player'。 有关更多信息,请参阅oTree 2.0。

 

模板中的表单

在模板中,您可以显示表单。{% formfields %}

{% formfields %} 于2018年6月推出。它相当于:

如果要单独定位字段,可以改为使用:{% formfield %}

您也可以将直接放在模板中:

注意:如果您之前编写过HTML表单,则可能习惯于编写<input>元素,例如: <input type =“text”name =“contribution”>。 在oTree中,通常使用formfield更容易。 它将自动生成正确的<input> HTML,以及CSS样式,标签和错误消息。 但是,如果您想要更灵活,可以自由编写原始HTML。 请参阅高级:原始HTML小部件。

form_model = ‘group’

如果你设置form_model ='group'。 用户提交的值将存储在组模型中,而不是玩家中。 这在一些玩家代表小组做出决定的游戏中通常很有用。 例如,在最后通牒博弈实验中,玩家1提出要求而玩家2接受或拒绝。 由于每组只提供1个要求,您可以在组中定义字段:

您的页面如下所示:

在您的模板中,您将拥有:

 

简单的表单字段验证

玩家必须在进入下一页之前提交有效表格。如果他们提交的表单无效(例如缺失或不正确的值),则会将其重新显示给他们以及他们需要纠正的错误列表。

oTree自动验证输入。 例如,如果您有一个包含IntegerField的表单,oTree将拒绝输入,如1.5或hello。

最小和最大

例如,这是你需要一个12到24之间的整数:

如果最大/最小值未修复,则应使用{field_name} _max()

选择

如果您希望字段为包含选项列表的下拉菜单,请设置choices=

要使用单选按钮而不是下拉菜单,您应该将小部件设置为RadioSelect或RadioSelectHorizontal:

如果需要动态确定选择列表,请使用{field_name} _choices()

您还可以通过列出[value,display]对来为每个选项设置显示名称:

如果您这样做,用户只会看到“低”,“中”,“高”的菜单,但他们的回复将被记录为1,2或3。

设置字段后,您可以使用get_FOO_display访问人类可读的名称,如下所示:self.get_level_display()#return,例如: '中'。 但是,如果使用{field_name} _choices()动态定义选项,为了使用get _ * _ display(),还需要在models.py中的Player / Group上定义* _choices方法。

可选字段

如果字段是可选的,您可以这样使用blank=True

然后HTML字段将没有该required属性。

 

动态表单字段验证

minmaxchoices上面描述仅用于固定的(恒定)值。

如果您希望动态确定它们(例如,不同于玩家),那么您可以在Page类中定义以下方法之一pages.py

{field_name} _choices()

就像choices=在models.py中设置一样,这将设置表单字段的选项(例如下拉菜单或单选按钮)。

{field_name} _max()

max=在models.py中设置的动态替代方法。例如:

{field_name} _min()

min在models.py中设置的动态替代方法。

{field_name} _error_message()

这是验证字段最灵活的方法。

例如,假设玩家必须进行购买,但此次购买不能超过玩家的预算。假设您的字段被调用purchase并且budget

一起验证多个字段

假设您的表单中有3个整数字段,其名称为 int1int2int3,并且提交的值必须总和为100.您可以使用以下error_message方法强制执行此操作:

 

动态确定表单域

如果您需要表单字段列表是动态的,而不是form_fields,您可以定义返回列表的方法get_form_fields(self)。 例如:

但是,如果这样做,您必须确保在模板中包含相同的{%formfield%}元素。 最简单的方法是使用{%formfields%}。

 

小部件

Django提供的表单输入小部件的完整列表就 在这里。

oTree另外提供:

  • RadioSelectHorizontalRadioSelect与水平布局相同,正如您将看到的Likert量表)
  • Slider
    • 要指定步长,请执行以下操作: Slider(attrs={'step': '0.01'})
    • 要禁用显示当前值,请执行以下操作: Slider(show_value=False)

 

自定义字段的外观

{%formfields%}和{%formfield%}易于使用,因为它们使用Bootstrap样式自动输出表单字段的所有必要部分(输入,标签和任何错误消息)。

但是,如果您想要更好地控制外观和布局,可以使用Django的手动场渲染。 不要{%formfield player.my_field%},而是{{form.my_field}},只获取输入,然后根据需要定位。

请记住还要包含{{form.my_field.errors}},这样如果表单中有错误,参与者将看到错误消息。

更多信息在这里。

示例:表格中的单选按钮和其他自定义布局

假设IntegerField您的模型中有一组:

并且您希望将它们呈现为一个类似的比例,其中每个选项都在一个单独的列中。

(首先,按照如何创建许多字段中的说明,尝试减少models.py中的代码重复。)

因为选项必须位于单独的表格单元格中,所以普通的RadioSelectHorizontal小部件在此处不起作用。

相反,您应该简单地循环遍历字段中的选项,如下所示:

如果您有许多具有相同选择数的字段,则可以将它们排列在表格中:

您还可以使用基于0的索引单独获取选项,例如 {{form.my_field.0}}为您提供了第一选择的单选按钮。 对于更精细的控制,如此处所述,您可以在字段选择上使用choice_label和tag属性。

 

高级:原始HTML小部件

如果和手动字段渲染 仍然不够灵活,您可以为表单输入编写原始HTML。但是,您将失去oTree自动处理的便捷功能。例如,如果表单有错误并且页面重新加载,则可能会清除用户的所有条目。{% formfield %}

要使用原始HTML,只需确保Page的每个字段form_fields 都有一个<input>具有匹配name属性的对应元素。

请记住,对于任何字段my_field,您应该包括,以便如果表单中有错误,参与者将看到错误消息。{{ form.my_field.errors }}

原始HTML示例:使用JavaScript的自定义用户界面

假设您不希望用户填写表单字段,而是与某种可视应用程序进行交互,例如点击图表或玩图形游戏。或者,您希望记录额外的数据,例如他们在页面的一部分上花了多长时间,他们点击了多少次等等。

您可以在任何所需的前端框架中构建这些接口。简单的可以使用jQuery完成; 更复杂的会使用像React或Polymer这样的东西。

然后,使用JavaScript记录相关数据点并将其存储在隐藏表单字段中。例如:

然后,您可以使用JavaScript设置该输入的值,方法是选择id的元素id_my_hidden_input,并设置其value属性。

提交页面时,隐藏输入的值将像任何其他表单字段一样记录在oTree中。

 

按钮

提交表单的按钮

如果您的页面只包含1个决定,则可以省略 ,而是让用户单击其中一个按钮转到下一页。{% next_button %}

例如,假设您的models.py有,而不是单选按钮,您希望将其显示为如下按钮:offer_accepted = models.BooleanField()

首先,像往常一样放入offer_accepted你的Page form_fields。然后将此代码放在模板中(这些btn类仅用于Bootstrap样式):

您可以将此技术用于任何类型的字段,而不仅仅是BooleanField

不提交表单的按钮

如果按钮除了提交表单之外有其他目的,请添加type="button"<button>

 

杂项和高级

具有动态矢量字段的表单

假设你想要一个带有n个字段向量相同的表单,除了一些数字索引,例如:

此外,假设n是可变的(范围从1到N)。

目前在oTree中,您只能在模型中定义固定数量的字段。因此,您应该在models.pyN fields(contribution_1...contribution_N...)中定义,然后get_form_fields如上所述使用动态返回包含这些字段的所需子集的列表。

例如,假设上面的变量n实际上是IntegerField玩家,它在游戏中的某个点动态设置。你可以get_form_fields 像这样使用:

带动态标签的表单字段

如果标签应包含变量,则可以在pages.py以下位置构造字符串:

然后在模板中,将标签设置为此变量:

如果您使用此技术,您可能还需要使用动态表单字段验证。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注