第一部分:简单的调查问卷(适用于PyCharm用户)¶
我们来创建一个简单的问卷调查–在第一个页面上,将询问参与人的姓名与年龄,之后在第二个页面上,将此信息展示给参与人.
创建应用¶
使用 cd
命令进入你创建的oTree项目文件夹,(文件夹中包含一个 settings.py
文件)。假设命名文件夹为 oTree
,你应该使用下面的指令:
cd oTree
然后,创建应用:
otree startapp my_simple_survey
然后在PyCharm中,前往刚刚创建的 my_simple_survey
文件夹。
Define models¶
打开 app.py
并找到含有 class Player(BasePlayer):
的那行,在这里定义数据库中玩家表有哪些列。让我们添加下面两个字段:
name
(StringField
, 意为文本型数据)age
(一个正整数字段)
class Player(BasePlayer):
name = models.StringField()
age = models.IntegerField()
定义模板¶
此调查问卷包含2个页面:
- 页面1:玩家输入姓名与年龄
- 页面2:玩家看到他们在之前的页面输入的数据
So, let’s make 2 HTML template files.
不妨将第一个页面命名为 MyPage.html
,填入内容如下:
{% extends "global/Page.html" %}
{% block title %}
Enter your information
{% endblock %}
{% block content %}
Please enter the following information.
{% formfields %}
{% next_button %}
{% endblock %}
第二个模板命名为 Results.html
.
{% extends "global/Page.html" %}
{% block title %}
Results
{% endblock %}
{% block content %}
<p>Your name is {{ player.name }} and your age is {{ player.age }}.</p>
{% next_button %}
{% endblock %}
Define pages¶
现在定义页面,页面包含了如何显示HTML模板的控制逻辑。
Since we have 2 templates, we need 2 Page
classes.
The names should match those of the templates (MyPage
and
Results
).
首先定义 MyPage
.这个页面包含一个表单,我们需要定义 form_model
与 form_fields
.
class MyPage(Page):
form_model = 'player'
form_fields = ['name', 'age']
现在来定义 Results
. 这一页面不含有表单或其他特殊属性,所以我们只需要写“pass”。
class Results(Page):
pass
If there is already a WaitPage
, you can delete that,
because WaitPages are only necessary for multi-player games.
Then, set your page_sequence
to MyPage
followed by Results
.
So, all in all, your pages should look like this:
class MyPage(Page):
form_model = 'player'
form_fields = ['name', 'age']
class Results(Page):
pass
page_sequence = [
MyPage,
Results
]
在settings.py中定义session config¶
现在打开在项目文件夹最上方的 settings.py
并在 SESSION_CONFIGS
中增加一个条目。
SESSION_CONFIGS = [
dict(
name='my_simple_survey',
num_demo_participants=3,
app_sequence=['my_simple_survey']
),
]
处理错误¶
如果你的代码中有错误,那么命令行会显示“traceback”(报错信息),一般格式如下:
Traceback (most recent call last):
File "C:\oTree\chris\manage.py", line 10, in <module>
execute_from_command_line(sys.argv, script_file=__file__)
File "c:\otree\core\otree\management\cli.py", line 170, in execute_from_command_line
utility.execute()
File "C:\oTree\venv\lib\site-packages\pkg\core\management\__init__.py", line 328, in execute
pkg.setup()
File "C:\oTree\venv\lib\site-packages\pkg\__init__.py", line 18, in setup
apps.populate(settings.INSTALLED_APPS)
File "C:\oTree\venv\lib\site-packages\pkg\apps\registry.py", line 108, in populate
app_config.import_models(all_models)
File "C:\oTree\venv\lib\site-packages\pkg\apps\config.py", line 198, in import_models
self.models_module = import_module(models_module_name)
File "C:\Python27\Lib\importlib\__init__.py", line 37, in import_module
__import__(name)
File "C:\oTree\chris\public_goods_simple\models.py", line 40
self.total_contribution = sum([p.contribution for p in self.get_players()])
^
IndentationError: expected an indented block
之所以称为“traceback”是因为它可以沿着代码调用链追踪错误。第一步你应当查看报错信息的最后一行。具体来说,在最后一条记录中找到文件名和行号。在上面的例子中,即 "C:\oTree\chris\public_goods_simple\models.py", line 40
.之后转到对应文件的对应行号。检查在traceback最后一行中提到的错误。在本例中,错误是 IndentationError: expected an indented block
(这表明了问题应当与代码缩进有关)。尝试修复这个错误并重新运行之前的命令。
有些时候traceback的最后一行没有指向你代码的一部分。如下例中的traceback,最后一行指向 /site-packages/easymoney.py
,这并不是你的应用的一部分,而是一个外部的包:
Traceback:
File "/usr/local/lib/python3.5/site-packages/pkg/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.5/site-packages/pkg/pages/generic/base.py" in view
71. return player.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/pkg/utils/decorators.py" in _wrapper
34. return bound_func(*args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/pkg/pages/decorators/cache.py" in _wrapped_view_func
57. response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/pkg/utils/decorators.py" in bound_func
30. return func.__get__(player, type(player))(*args2, **kwargs2)
File "/usr/local/lib/python3.5/site-packages/pkg/utils/decorators.py" in _wrapper
34. return bound_func(*args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/pkg/pages/decorators/cache.py" in _cache_controlled
43. response = viewfunc(request, *args, **kw)
File "/usr/local/lib/python3.5/site-packages/pkg/utils/decorators.py" in bound_func
30. return func.__get__(player, type(player))(*args2, **kwargs2)
File "/usr/local/lib/python3.5/site-packages/otree/pages/abstract.py" in dispatch
315. request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/pkg/pages/generic/base.py" in dispatch
89. return handler(request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/otree/pages/abstract.py" in get
814. return super(FormPageMixin, player).get(request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/vanilla/model_views.py" in get
294. context = player.get_context_data(form=form)
File "/usr/local/lib/python3.5/site-packages/otree/pages/abstract.py" in get_context_data
193. vars_for_template = player.resolve_vars_for_template()
File "/usr/local/lib/python3.5/site-packages/otree/pages/abstract.py" in resolve_vars_for_template
212. context.update(player.vars_for_template() or {})
File "/Users/chris/oTree/public_goods/pages.py" in vars_for_template
108. 'total_payoff': player.player.payoff + Constants.fixed_pay}
File "/usr/local/lib/python3.5/site-packages/easymoney.py" in <lambda>
36. return lambda player, other, context=None: player.__class__(method(player, _to_decimal(other)))
File "/usr/local/lib/python3.5/site-packages/easymoney.py" in _to_decimal
24. return Decimal(amount)
Exception Type: TypeError at /p/j0p7dxqo/public_goods/ResultsFinal/8/
Exception Value: conversion from NoneType to Decimal is not supported
在这种情况下,查看是否你的代码的某部分被包含在traceback中。我们可以从上面的traceback中看出它包含了文件 /Users/chris/oTree/public_goods/pages.py
,这一文件正是我们项目的一部分。而错误就在该文件的108行,如traceback所提示的一样。