1

我想使用 oTree 作为进行实验的替代方法。为此,我正在寻找一种在表单中包含强制性滑块问题的可能性,即在您能够继续下一个问题之前,您需要移动滑块。作为开始,我尝试修改 oTrees调查模板以实现未来使用的解决方案,但无法将 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
]

提前致谢!

4

3 回答 3

3

有两种方法:仅在客户端使用 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事件之前,SliderTOuchedvar 被设置为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 %}
于 2017-05-29T20:17:25.820 回答
0

默认情况下,Django 假设输入是必需的

我认为这意味着如果您只删除初始值,它将自我验证。

此外,您调用了一个名为“IntegerFielder()”的东西。您是说 models.IntegerField() 还是我们没有看到的导入?

于 2017-01-06T19:41:34.087 回答
0

我建议对菲利普的回答稍作修改。

如果参与者触摸滑块,上面的代码仍然会触发错误消息,但会将滑块返回到默认的起始位置。

为了解决这个问题,我使用了以下脚本:

{% block scripts %}
    <script>
        $('input[name=q_age]').on('input', function(){
            $('#id_checkslider').val(1);
        });
    </script>
{% endblock %}

即使参与者将滑块设置为默认起始位置,代码也会checksliderNone到触摸滑块。1

于 2018-04-05T12:13:13.930 回答