高级特性

这些高级特性大多数在oTree Studio中不被支持。

ExtraModel

An ExtraModel is useful when you need to store dozens or hundreds of data points about a single player. For example, a list of bids, or a list of stimuli and reaction times. They are frequently used together with 实时页面.

There are a bunch of examples here.

An ExtraModel should link to another model:

class Bid(ExtraModel):
    player = models.Link(Player)
    amount = models.CurrencyField()

Each time the user makes a bid, you store it in the database:

Bid.create(player=player, amount=500)

Later, you can retrieve the list of a player’s bids:

bids = Bid.filter(player=player)

An ExtraModel can have multiple links:

class Offer(ExtraModel):
    sender = models.Link(Player)
    receiver = models.Link(Player)
    group = models.Link(Group)
    amount = models.CurrencyField()
    accepted = models.BooleanField()

Then you can query it in various ways:

this_group_offers = Offer.filter(group=group)
offers_i_accepted = Offer.filter(receiver=player, accepted=True)

For more complex filters and sorting, you should use list operations:

offers_over_500 = [o for o in Offer.filter(group=group) if o.amount > 500]

See the example psychology games such as the Stroop task, which show how to generate ExtraModel data from each row of a CSV spreadsheet.

模板

template_name

如果模板需要有一个与你的页面类不同的名字(例如你在不同的页面中共享同一模板),设置 template_name 即可。例如:

class Page1(Page):
    template_name = 'app_name/MyPage.html'

CSS/JS 与基模板

To include the same JS/CSS in all pages of an app, either put it in a ref:static file <staticfiles> or put it in an includable template.

静态文件

下面说明了如何在页面中包含图片(或任何静态文件如.css, .js,等等)。

At the root of your oTree project, there is a _static/ folder. Put a file there, for example puppy.jpg. Then, in your template, you can get the URL to that file with {{ static 'puppy.jpg' }}.

要显示图片,使用 <img> 标签,如:

<img src="{{ static 'puppy.jpg' }}"/>

上面我们将文件保存在 _static/puppy.jpg,但是实际上更好的做法是创建一个子文件夹,起名为你应用的名字,并存为 _static/your_app_name/puppy.jpg ,这使得文件组织有条理,并避免了名字冲突。

此时你的HTML代码变为:

<img src="{{ static 'your_app_name/puppy.jpg }}"/>

(如果你愿意的话,你也可以将静态文件放入你的应用文件夹,在子文件夹 static/your_app_name 中。)

如果静态文件在你更改了之后仍不改变,这是因为你的浏览器缓存了这个文件。重载整个页面即可(通常快捷键是 Ctrl+F5)

如果你需要视频或者高解析度的图片,更好的做法是将其存储在线上别的地方并使用URL进行引用。因为大文件使得上传 .otreezip文件非常缓慢。

等待页面

自定义等待页面模板

你可以自定义等待页面模板。例如,存为 your_app_name/templates/your_app_name/MyWaitPage.html:

{{ block title }}{{ title_text }}{{ endblock }}
{{ block content }}
    {{ body_text }}
    <p>
        My custom content here.
    </p>
{{ endblock }}

然后在等待页面中使用这一模板:

class MyWaitPage(WaitPage):
    template_name = 'your_app_name/MyWaitPage.html'

此时你可以如寻常一样使用 vars_for_template 。实际上, body_texttitle_text 属性就是设置 vars_for_template 的简略方式;下面两段代码是等价的:

class MyWaitPage(WaitPage):
    body_text = "foo"
class MyWaitPage(WaitPage):

    @staticmethod
    def vars_for_template(player):
        return dict(body_text="foo")

如果你想全局应用你的自定义等待页面模板,将其保存在 _templates/global/WaitPage.html.oTree将自动地在所有地方使用它替换内置的等待页面。

货币

为将”points”自定义为别的名字如”tokens” 或 “credits”, 设置 POINTS_CUSTOM_NAME ,例如 POINTS_CUSTOM_NAME = 'tokens'.

你可以改变真实世界货币的小数位数,通过设置 REAL_WORLD_CURRENCY_DECIMAL_PLACES。如果额外的小数位数显示出来但总是0,那么你应当重置数据库。

读入CSV或其他文件

Store yourfile.csv in your app folder. Then put this code anywhere you want to read the file (in a function or in Constants):

import csv
with open('yourapp/yourfile.csv', encoding='utf-8') as file:
    rows = list(csv.DictReader(file))

如果文件不是CSV格式并且你想读入文件内容为一个字符串,代码简化为:

with open('yourapp/yourfile.txt', encoding='utf-8') as file:
    txt = file.read()