oTree/django 中的强制滑块
Mandatory slider in oTree/django
我想使用 oTree 作为进行实验的替代方案。为此,我正在寻找在表格中包含强制性滑块问题的可能性,即。 e.在您能够继续下一个问题之前,您需要移动滑块。一开始,我尝试修改 oTrees survey template 以实现未来使用的解决方案,但无法将 fieldtracker 等常用方法集成到项目中。
这是 models.py 和 views.py 文件的两个修改版本(但目前经过多次不成功的尝试后还没有真正发挥作用),它们提示了我想去的方向.有没有办法让它发挥作用?
# -*- coding: utf-8 -*-
## models.py
# <standard imports>
from __future__ import division
from django.db import models
from django_countries.fields import CountryField
from model_utils import FieldTracker,
from otree import widgets
from otree.constants import BaseConstants
from otree.db import models
from otree.models import BaseSubsession, BaseGroup, BasePlayer
class Constants(BaseConstants):
name_in_url = 'survey'
players_per_group = None
num_rounds = 1
class Subsession(BaseSubsession):
pass
class Group(BaseGroup):
pass
class Player(BasePlayer):
def set_payoff(self):
"""Calculate payoff, which is zero for the survey"""
self.payoff = 0
q_country = CountryField(
verbose_name='What is your country of citizenship?')
q_age = IntegerFielder(verbose_name='What is your age?',
min=13, max=125,
initial=25,
widget=widgets.SliderInput())
q_gender = models.CharField(initial=None,
choices=['Male', 'Female'],
verbose_name='What is your gender?',
widget=widgets.RadioSelect())
tracker = FieldTracker()
crt_bat = models.PositiveIntegerField()
crt_widget = models.PositiveIntegerField()
crt_lake = models.PositiveIntegerField()
第二个文件来了:
# -*- coding: utf-8 -*-
##views.py
from __future__ import division
from . import models
from ._builtin import Page, WaitPage
from otree.common import Currency as c, currency_range
from .models import Constants, integerfieldcustom
class Demographics(Page):
form_model = models.Player
form_fields = ['q_country',
'q_age',
'q_gender']
check_age = q_age.tracker.has_changed()
def q_age_error_message(self, ):
if Demographics.check_age == False:
return 'You must move the slider before you can continue'
class CognitiveReflectionTest(Page):
form_model = models.Player
form_fields = ['crt_bat',
'crt_widget',
'crt_lake']
def before_next_page(self):
self.player.set_payoff()
page_sequence = [
Demographics,
CognitiveReflectionTest
]
提前致谢!
默认情况下,Django assumes an input is required。
我认为这意味着如果您只是删除初始值,它将自我验证。
另外,你调用了一个名为 "IntegerFielder()." 的东西你是说 models.IntegerField() 还是有一个我们没有看到的导入?
有两种方法:在客户端仅使用 JS,在服务器端使用 Django。
简单的JS解决方案:
在模板中添加:
{% block scripts %}
<script>
var SliderTouched = false;
var selector = $('[data-slider] input[type="range"]');
selector.change(function() {
SliderTouched = true;
});
$( ".form" ).submit(function( event ) {
if (!SliderTouched){
event.preventDefault();}
});
</script>
{% endblock %}
因此,在用户触发 change
事件之前,SliderTOuched
var 将设置为 False
,从而阻止提交表单。这是一种紧凑的方式,但您必须自己处理向用户显示错误消息。
=================
较长的服务器端解决方案如下:
在models.py
中定义一个附加字段:
class Player(BasePlayer):
checkslider = models.IntegerField(blank=True)
在 views.py
中,除了您的滑块字段外,还要传递这个额外的字段来检查滑块是否已更改:
class MyPage(Page):
form_model = models.Player
form_fields = ['q_age', 'checkslider']
def checkslider_error_message(self, value):
if not value:
return 'Please make your decision using slider'
在模板中将这个隐藏的额外字段插入到 html:
<input type="hidden" name="checkslider" value="" id="id_checkslider"/>
并在更改滑块后立即将此字段设置为当前滑块值:
{% block scripts %}
<script>
var selector = $('[data-slider] input[type="range"]');
selector.change(function() {
$('#id_checkslider').val(selector.val());
});
</script>
{% endblock %}
我建议对 Philipp 的回答稍作修改。
如果参与者触摸滑块,但 returns 滑块移动到默认起始位置,上面的代码仍会触发错误消息。
为了解决这个问题,我使用了以下脚本:
{% block scripts %}
<script>
$('input[name=q_age]').on('input', function(){
$('#id_checkslider').val(1);
});
</script>
{% endblock %}
触摸滑块时,代码将 checkslider
从 None
更改为 1
,即使参与者将滑块设置为默认起始位置也是如此。
我想使用 oTree 作为进行实验的替代方案。为此,我正在寻找在表格中包含强制性滑块问题的可能性,即。 e.在您能够继续下一个问题之前,您需要移动滑块。一开始,我尝试修改 oTrees survey template 以实现未来使用的解决方案,但无法将 fieldtracker 等常用方法集成到项目中。
这是 models.py 和 views.py 文件的两个修改版本(但目前经过多次不成功的尝试后还没有真正发挥作用),它们提示了我想去的方向.有没有办法让它发挥作用?
# -*- coding: utf-8 -*-
## models.py
# <standard imports>
from __future__ import division
from django.db import models
from django_countries.fields import CountryField
from model_utils import FieldTracker,
from otree import widgets
from otree.constants import BaseConstants
from otree.db import models
from otree.models import BaseSubsession, BaseGroup, BasePlayer
class Constants(BaseConstants):
name_in_url = 'survey'
players_per_group = None
num_rounds = 1
class Subsession(BaseSubsession):
pass
class Group(BaseGroup):
pass
class Player(BasePlayer):
def set_payoff(self):
"""Calculate payoff, which is zero for the survey"""
self.payoff = 0
q_country = CountryField(
verbose_name='What is your country of citizenship?')
q_age = IntegerFielder(verbose_name='What is your age?',
min=13, max=125,
initial=25,
widget=widgets.SliderInput())
q_gender = models.CharField(initial=None,
choices=['Male', 'Female'],
verbose_name='What is your gender?',
widget=widgets.RadioSelect())
tracker = FieldTracker()
crt_bat = models.PositiveIntegerField()
crt_widget = models.PositiveIntegerField()
crt_lake = models.PositiveIntegerField()
第二个文件来了:
# -*- coding: utf-8 -*-
##views.py
from __future__ import division
from . import models
from ._builtin import Page, WaitPage
from otree.common import Currency as c, currency_range
from .models import Constants, integerfieldcustom
class Demographics(Page):
form_model = models.Player
form_fields = ['q_country',
'q_age',
'q_gender']
check_age = q_age.tracker.has_changed()
def q_age_error_message(self, ):
if Demographics.check_age == False:
return 'You must move the slider before you can continue'
class CognitiveReflectionTest(Page):
form_model = models.Player
form_fields = ['crt_bat',
'crt_widget',
'crt_lake']
def before_next_page(self):
self.player.set_payoff()
page_sequence = [
Demographics,
CognitiveReflectionTest
]
提前致谢!
默认情况下,Django assumes an input is required。
我认为这意味着如果您只是删除初始值,它将自我验证。
另外,你调用了一个名为 "IntegerFielder()." 的东西你是说 models.IntegerField() 还是有一个我们没有看到的导入?
有两种方法:在客户端仅使用 JS,在服务器端使用 Django。
简单的JS解决方案: 在模板中添加:
{% block scripts %}
<script>
var SliderTouched = false;
var selector = $('[data-slider] input[type="range"]');
selector.change(function() {
SliderTouched = true;
});
$( ".form" ).submit(function( event ) {
if (!SliderTouched){
event.preventDefault();}
});
</script>
{% endblock %}
因此,在用户触发 change
事件之前,SliderTOuched
var 将设置为 False
,从而阻止提交表单。这是一种紧凑的方式,但您必须自己处理向用户显示错误消息。
=================
较长的服务器端解决方案如下:
在models.py
中定义一个附加字段:
class Player(BasePlayer):
checkslider = models.IntegerField(blank=True)
在 views.py
中,除了您的滑块字段外,还要传递这个额外的字段来检查滑块是否已更改:
class MyPage(Page):
form_model = models.Player
form_fields = ['q_age', 'checkslider']
def checkslider_error_message(self, value):
if not value:
return 'Please make your decision using slider'
在模板中将这个隐藏的额外字段插入到 html:
<input type="hidden" name="checkslider" value="" id="id_checkslider"/>
并在更改滑块后立即将此字段设置为当前滑块值:
{% block scripts %}
<script>
var selector = $('[data-slider] input[type="range"]');
selector.change(function() {
$('#id_checkslider').val(selector.val());
});
</script>
{% endblock %}
我建议对 Philipp 的回答稍作修改。
如果参与者触摸滑块,但 returns 滑块移动到默认起始位置,上面的代码仍会触发错误消息。
为了解决这个问题,我使用了以下脚本:
{% block scripts %}
<script>
$('input[name=q_age]').on('input', function(){
$('#id_checkslider').val(1);
});
</script>
{% endblock %}
触摸滑块时,代码将 checkslider
从 None
更改为 1
,即使参与者将滑块设置为默认起始位置也是如此。