模板

模板语法

变量

你可以像下面这样显示一个变量:

Your payoff is {{ player.payoff }}.

下面的变量在模板中均可用:

  • player: 当前正在浏览页面的玩家
  • group: 当前玩家所属的小组
  • subsession: 当前玩家所属的子会话
  • participant: 当前玩家所属的参与人
  • session: 当前会话
  • Constants
  • 任何你使用 vars_for_template() 传递的变量。

条件(“if”)

{% if player.is_winner %} you won! {% endif %}

使用‘else’:

{% if some_number >= 0 %}
    positive
{% else %}
    negative
{% endif %}

循环(“for”)

{% for item in some_list %}
    {{ item }}
{% endfor %}

获取字典中的元素

在Python代码中使用 my_dict['foo'], 但在模板中应当使用 {{ my_dict.foo }}.

注释

{% comment %}
this is a comment
{% endcomment %}

不应当使用的语法

模板语言仅仅是为了显示值。你不能在其中做数学运算 (+, *, /, -) 或者修改数字,列表,字符串等等。为了修改变量,应当使用 vars_for_template().

模板是如何工作的:一个例子

oTree模板是两种语言的混合:

  • HTML (使用尖角括号如 <this></this>.
  • Template tags (which use curly braces like {% this %} and {{ 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 %}

Step 1: oTree scans template tags, produces HTML (a.k.a. “server side”)

oTree uses the current values of the variables to convert the above template tags to plain HTML, like this:

<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页面:

_images/template-example.png

Note that the browser never sees the template tags.

要点

如果页面没有如期望正常工作,你可以分开来看上面两步哪一步出错了。在浏览器中,右键单击并“查看源代码”。(注意:“查看源代码”在分离屏幕模式下可能无法正常工作。)

你可以看到生成的纯HTML(与JavaScript和CSS)。

  • If the HTML code doesn’t look the way you expect, then something went wrong on the server side. Look for mistakes in your vars_for_template or your template tags.
  • If there was no error in generating the HTML code, then it is probably an issue with how you are using HTML (or JavaScript) syntax. Try pasting the problematic part of the HTML back into a template, without the template tags, and edit it until it produces the right output. Then put the template tags back in, to make it dynamic again.

图片(静态文件)

在项目中包含图片,视频,第三方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 中构建并将其传递给模板,例如:

def vars_for_template(player):
    return dict(
        image_path='my_app/{}.png'.format(player.round_number)
    )

在模板中使用:

<img src="{% static image_path %}"/>

可包含的模板

如果你将同样的内容在多个模板之间复制粘贴,更好的方案是创建一个可包含的模板并使用 {% include %} 复用模板。

举例来说,如果在你的游戏中游戏说明需要在每一个页面上重复出现,那么就可以创建一个模板,叫做 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>

如果你使用的是oTree Studio,点击一个按钮即可包含一个模板。如使用文本编辑器,则在 templates 文件夹中创建文件,然后查看简单的游戏示例来弄明白如何包含模板(例如 instructions_template)。

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>

获取更多信息,可在浏览器中右键单击你想要修改的元素并选择“审查元素”。然后你可以导航到不同元素并试着改变它们的样式:

_images/dom-inspector.png

尽可能使用上面给出的官方选择器。不要使用任何以 _otree 开头或者基于Bootstrap类的选择器,如 btn-primarycard,它们都是不稳定的。

从Python向JavaScript传递数据(js_vars)

为了在模板中向JavaScript代码传递数据,定义一个 js_vars 方法在你的页面中,例如:

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会在手机或平板上试着显示一个“移动端友好”的版本。

图表

你可以使用任何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> 标签。

一旦你的图表加载正常,你就可以将硬编码的数据替换为 seriescategories 这样动态生成的变量。

例如,将这个:

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 中定义的变量。

如果你的图表没有加载,在浏览器中单击“查看源码”检查是否是动态生成的数据出现了问题。

Miscellaneous

You can round numbers using the to2, to1, or to0 filters. For example:: {{ 0.1234|to2}} outputs 0.12.