模板¶
模板语法¶
变量¶
你可以像下面这样显示一个变量:
Your payoff is {{ player.payoff }}.
下面的变量在模板中均可用:
player
: 当前正在浏览页面的玩家group
: 当前玩家所属的小组subsession
: 当前玩家所属的子会话participant
: 当前玩家所属的参与人session
: 当前会话C
- 任何你使用 vars_for_template() 传递的变量。
条件(“if”)¶
注解
oTree 3.x 在模板中使用两种不同的标签:{{ }}
与 {% %}
。但从oTree 5开始,你可以忘了 {% %}
并在任何你想使用的地方只用 {{ }}
。旧格式仍然可用。
使用‘else’:
Complex example:
循环(“for”)¶
{{ for item in some_list }}
{{ item }}
{{ endfor }}
获取字典中的元素¶
在Python代码中使用 my_dict['foo']
的地方,在模板中应当使用 {{ my_dict.foo }}
。
注释¶
{# this is a comment #}
{#
this is a
multiline comment
#}
不正确的使用¶
模板语言仅仅是为了显示值。你不能在其中做数学运算 (+
, *
, /
, -
) 或者修改数字,列表,字符串等等。想要做这些事情,应当使用 vars_for_template()。
模板是如何工作的:一个例子¶
oTree模板是两种语言的混合:
- HTML (使用尖角括号如
<this>
与</this>
。) - 模板标签 (使用大括号如
{{ this }}
与{{ this }}
)
在这个例子中,假定你的模板如下:
<p>Your payoff this round was {{ player.payoff }}.</p>
{{ if subsession.round_number > 1 }}
<p>
Your payoff in the previous round was {{ last_round_payoff }}.
</p>
{{ endif }}
{{ next_button }}
步骤1:oTree扫描模板标签,生成HTML(亦称“服务器端”)¶
oTree使用变量当前的值将模板标签转换为纯HTML,像下面这样:
<p>Your payoff this round was $10.</p>
<p>
Your payoff in the previous round was $5.
</p>
<button class="otree-btn-next btn btn-primary">Next</button>
步骤2:浏览器扫描HTML标签,生成web页面(亦称“浏览器端”)¶
oTree服务器将HTML发送给用户的电脑,用户的web浏览器可以解析这些代码并将其显示为格式化的web页面:

注意浏览器永远不会收到模板标签。
要点¶
如果页面没有如期望正常工作,你可以分开来看上面两步中哪一步出错了。在浏览器中,右键单击并“查看源代码”。(注意:“查看源代码”在分离屏幕模式下可能无法正常工作。)
你可以看到生成的纯HTML(与JavaScript和CSS)。
- 如果HTML代码看起来不是所期望的,那么可能服务器端出现了某种问题。可在
vars_for_template
或者模板标签中寻找错误。 - 如果生成的HTML代码没有任何错误,那么可能你使用了错误的HTML(或者JavaScript)语法。试着将HTML有问题的部分粘贴回模板中,去掉模板标签,编辑它直到输出正常。再尝试将模板标签加回去,使得页面重新成为动态的。
图片(静态文件)¶
在项目中包含图片,视频,第三方JS/CSS库或者其他静态文件的最简单的方法是将它们在线存放,例如使用Dropbox,Imgur,YouTube等等。
然后,将URL包含在 <img> 或 <video> 标签内放在模板中,例如:
<img src="https://i.imgur.com/gM5yeyS.jpg" width="500px" />
你也可以直接将图片存放在你的项目中。(但注意文件较大会影响性能)。oTree Studio有一个图片上传工具。(如果你使用文本编辑器,参考 这里。)将图片存储在项目中后,你可以像下面这样显示它:
<img src="{{ static 'folder_name/puppy.jpg' }}"/>
动态图片¶
如果你需要根据上下文显示不同的图片(比如每一轮显示不同的图片),那么你可以在 vars_for_template
中构建并将其传递给模板,例如:
@staticmethod
def vars_for_template(player):
return dict(
image_path='my_app/{}.png'.format(player.round_number)
)
然后在模板中使用:
<img src="{{ static image_path }}"/>
可包含的模板¶
如果你将相同的内容在多个模板之间复制粘贴,更好的方案是创建一个可包含的模板并使用 {{ include_sibling }}
复用模板。
举例来说,如果在你的游戏中游戏说明需要在每一个页面上重复出现,那么就可以创建一个模板,叫做 instructions.html
,并将说明放入其中,例如:
<div class="card bg-light">
<div class="card-body">
<h3>
Instructions
</h3>
<p>
These are the instructions for the game....
</p>
</div>
</div>
Then use {{ include_sibling 'instructions.html' }}
to insert it anywhere you want.
注解
{{ include_sibling }}
is a new alternative to {{ include }}
.
The advantage is that you can omit the name of the app: {{ include_sibling 'xyz.html' }}
instead of {{ include 'my_app/xyz.html' }}
.
However, if the includable template is in a different folder, you must use {{ include }}
.
JavaScript 与 CSS¶
将JavaScript/CSS代码放在何处¶
你可以使用常见的 <script></script>
或 <style></style>
标签将JavaScript与CSS放在你模板的任意位置。
如果你有很多脚本/样式,你可以将它们放在 content
之外独立的部分: scripts
and styles
中。这并非强制的要求,但这样做会使你的代码更有条理并确保页面按照顺序加载(CSS,然后是页面内容,然后是JavaScript)。
定制主题¶
如果你想要定制oTree元素的外观,下表列出了CSS选择器:
元素 | CSS/jQuery 选择器 |
---|---|
页面主体 | .otree-body |
页面标题 | .otree-title |
等待页面(整个对话框) | .otree-wait-page |
等待页面对话框标题 | .otree-wait-page__title (注意: __ , 而非 _ ) |
等待页面对话框主体 | .otree-wait-page__body |
计时器 | .otree-timer |
下一步按钮 | .otree-btn-next |
表单错误警告 | .otree-form-errors |
举例来说,想要改变页面宽度,将CSS在基模板中放置如下:
<style>
.otree-body {
max-width:800px
}
</style>
获取更多信息,可在浏览器中右键单击你想要修改的元素并选择“审查元素”。然后你可以导航到不同元素并试着改变它们的样式:

尽可能使用上面给出的官方选择器。不要使用任何以 _otree
开头或者基于Bootstrap类的选择器,如 btn-primary
或 card
,因为它们是不稳定的。
从Python向JavaScript传递数据(js_vars)¶
为了在模板中向JavaScript代码传递数据,在你的页面中定义一个 js_vars
方法,例如:
@staticmethod
def js_vars(player):
return dict(
payoff=player.payoff,
)
在模板中,你就可以像下面这样引用这些变量:
<script>
let x = js_vars.payoff;
// etc...
</script>
Bootstrap¶
oTree使用了 Bootstrap,一个流行的用于定制网站用户界面的库。
如果你想要 定制样式,或者 特定组件 如表格,警告,进度条,标签,等等,你可以使用此库。你甚至可以让你的页面变得动态,通过使用组件如 popovers, modals, 和 collapsible text。
使用Bootstrap,通常需要在HTML元素中添加一个 class=
属性。
举例来说,下面得HTML会创建一个“Success” 警告:
<div class="alert alert-success">Great job!</div>
移动设备¶
Bootstrap会在手机或平板上试着显示一个“移动端友好”的版本。
Best way to test on mobile is to use Heroku.otree zipserver
doesn’t accept a ‘port’ argument. Also, devserver/zipserver seem to have issues with shutdown/reloading and freeing up the port.
图表¶
你可以使用任何HTML/JavaScript库来为你的应用添加图表。HighCharts 是一个不错的选择,它可以用来画饼状图,折线图,直方图,时间序列等等。
首先,引入HighCharts JavaScript:
<script src="https://code.highcharts.com/highcharts.js"></script>
在HighCharts demo site 寻找你想要的图表类型。然后点击”edit in JSFiddle”将其编辑成你想要的样子,使用硬编码数据。
然后,复制粘贴JS与HTML到你的模板中,并加载页面。如果你没有看到你的图表,可能是因为JS代码试图插入图表的那一部分HTML缺少了 <div>
标签。
一旦你的图表加载正常,你就可以将硬编码的数据替换为 series
和 categories
这样动态生成的变量。
例如,将下面的代码:
series: [{
name: 'Tokyo',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
}, {
name: 'New York',
data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
}]
改为:
series: js_vars.highcharts_series
…此处 highcharts_series
是你在 js_vars 中定义的变量。
如果你的图表没有加载,在浏览器中单击“查看源码”检查是否是动态生成的数据出现了问题。
杂项¶
你可以使用 to2
,to1
, 或 to0
过滤器来对数字取整。例如: {{ 0.1234|to2}}
的输出是 0.12。