otree 中的靈活實驗室實驗
我正在通過otree建構一個實驗室實驗,這是一個基於 Django 的框架,用於實現多人決策策略遊戲。
otree 形式的基礎知識
這是 otree 如何讓玩家報告他們的選擇的範例(基於“matching_pennies”遊戲,它是 otree 提供的模板的一部分)。
在一個名為 的文件
model.py
中,可以找到以下程式碼class Player(otree.models.BasePlayer): [...] penny_side = models.CharField(choices=['Heads', 'Tails']) [...]
然後在
views.py
一個發現class Choice(Page): form_model = models.Player form_fields = ['penny_side']
choice.html
最後,通過插入將表單顯示給最終使用者{% formfield player.penny_side with label="I choose:" %}
我想做什麼
是創建一個靈活的實驗,其中玩家必須做出的選擇數量隨參數而變化
x
。也就是說,我希望整個框架x
通過設置一個參數來生成可能的選擇x
,而不必手動更新所有文件。這是為了在我們更改實驗設計時讓我的生活更輕鬆,並使程式碼對其他具有不同實驗設計的人有用(我計劃在某個時候在 Github 上發布它)。使用幾個循環似乎應該相當容易,但是考慮到
otree
結構化的方式,我在使用列表時遇到了麻煩。據我了解,我只看到一種非常討厭的方式,讓選擇的數量取決於一個參數
x
。我首先給每個選項一個不同的名稱model.py
,例如class Player(otree.models.BasePlayer): [...] for i in range(x): exec("""choice%d = models.IntegerField( choices= ['Heads','Tails'])""" %i) [...]
然後將所有這些選項的名稱傳遞給
view.py
,例如class Choice(Page): all_forms = list() for i in range(x): all_forms.append('choice%d' %i) form_model = models.Player form_fields = all_forms
最後,找到一種方法來遍歷 Choice.html 中的所有表單;類似的東西(我知道下面的程式碼不起作用,只是為了給出它的要點)
{% for p in range(x) %} {% formfield player.choice{{p}} with label="I choose:" %} {% endfor %}
我的問題是:
- 這一切都很骯髒,而且看起來過於復雜:發明了列表來避免這種瘋狂的命名過程。您是否看到了一種使用列表來代替它的方法?
- 如果這是破解 otree 並讓選項數量取決於參數的唯一方法,那就
x
這樣吧。但是我仍然無法找到一種方法來通過 Django 中的循環生成所需的表單集(顯然上面的範例不起作用,原因有很多。)。
我在這裡找到了問題第二部分的答案https://github.com/oTree-org/otree-docs/issues/2。
事實證明,在 中
oTree
,傳遞給模板的變數form
是可迭代的。因此,以下程式碼可以完成這項工作:{% for field in form %} {% formfield field %} {% endfor %}
關於問題的第一部分,我聯繫了一位在 oTree 工作的程序員。他確認,在其目前版本中,oTree 只能定義固定數量的欄位。他建議定義
model.py
最大數量的欄位,然後get_form_fields
在 views.py 中使用以動態返回包含所需欄位子集的列表。請注意,如果您想創建非常多的最大欄位數,問題中提出的技巧使用
loop
andexec
仍然是 - 我相信 - 最簡單的方法。