模型¶
一个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)
内置字段与方法¶
玩家,小组与子会话有一些预定义的字段。举例来说, Player
有 payoff
与 id_in_group
字段, in_all_rounds()
与 get_others_in_group()
方法。
这些内置的字段与方法列出如下。
常量¶
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
中,因为这一函数在用户刷新页面时会重新执行)。