模型

一个oTree应用有3个数据模型:子会话,小组与玩家。

玩家是小组的一部分,小组是子会话的一部分。参考 概念总览

假设你想要你的实验生成下面这样的数据:

name    age is_student
John    30  False
Alice   22  True
Bob     35  False
...

下面的代码展示了如何定义上面的表结构:

class Player(BasePlayer):
    name = models.StringField()
    age = models.IntegerField()
    is_student = models.BooleanField()

所以,一个 模型 实际上就是一张数据库表。一个 字段 就是表中的一列。

字段

字段类型

  • BooleanField (表示 true/false 或者 yes/no 这样的值)
  • CurrencyField 表示货币数量; 参见 货币
  • IntegerField
  • FloatField (表示实数)
  • StringField (表示字符串)
  • LongStringField (表示长字符串; 它的表单控件是一个多行文本框)

初始/默认值

字段的初始值为 None,除非你设置了 initial=:

class Player(BasePlayer):
    some_number = models.IntegerField(initial=0)

最小值,最大值,可选项

如何设置字段的 minmax, 或 choices,参考 简单的表单验证

内置字段与方法

玩家,小组与子会话有一些预定义的字段。举例来说, Playerpayoffid_in_group 字段, in_all_rounds()get_others_in_group() 方法。

这些内置的字段与方法列出如下。

子会话

round_number

给出当前是第几轮。仅在应用有多轮时有意义(轮数由 C.NUM_ROUNDS 设置 )。参考 轮次

get_groups()

返回一个包含子会话中所有小组的列表。

get_players()

返回一个包含子会话中所有玩家的列表。

玩家

id_in_group

自动被赋值为从1开始的正整数。在多人游戏中,表示哪位是玩家1,哪位是玩家2,诸如此类。

payoff

玩家在本轮的收益。参考 收益

round_number

给出当前是第几轮。

会话

num_participants

会话中参与人的数量。

vars

参考 会话字段

参与人

id_in_session

会话中参与人的ID。这与玩家的 id_in_subsession 相同。

其他参与人属性与方法

常量

C 是推荐存放应用的参数或是玩家之间没有区别的常量的地方。

下面是内置的常量:

如果你不想让自己应用的真实名字被显示在URL中,那么可以定义一个字符串常量 NAME_IN_URL 并赋予你想显示的名字。

常量可以是数字,字符串,布尔值,列表等等类型。但对于更复杂的数据类型如字典,字典的列表等等,你应当在子会话方法中定义,而不是在常量中。举例来说,不要在常量中定义 my_dict ,而应当使用如下代码:

def my_dict(subsession):
    return dict(a=[1,2], b=[3,4])

杂项

关于使用 random()

永远不要在函数外部生成随机值。举例来说,不要写下面这样的代码:

class C(BaseConstants):
    P = random.randint(1, 10) # wrong

如果它随机变化,它就不算一个常量。

或者这样的代码:

class Player(BasePlayer):

    p = models.FloatField(
        # wrong
        initial=random.randint(1, 10)
    )

上述代码不会正常工作,因为随机值在服务器启动一个新进程时会改变。这可能在测试时工作正常,但最终会出现错误。相反的,你应该在函数内部生成随机值,如 实验组 中(尽量不要在 vars_for_template 中,因为这一函数在用户刷新页面时会重新执行)。