Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/439.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在CallbackJS中更改源数据_Javascript_Python_Django_Bokeh - Fatal编程技术网

Javascript 在CallbackJS中更改源数据

Javascript 在CallbackJS中更改源数据,javascript,python,django,bokeh,Javascript,Python,Django,Bokeh,我正试图在Django应用程序中创建一个bokeh图,为一名运动员绘制游泳项目图。我正在绘制游泳的持续时间和游泳比赛的日期。其想法是拥有一个绘图,并能够使用SelectBox小部件选择图形上显示的事件。问题是,当我在CallbackJS函数中更改数据源时,图形不会更新,而是变为空白 数据来自表单的事件对象 class Event(models.Model): swimmer = models.ForeignKey(Swimmer, on_delete=models.SET_NULL, n

我正试图在Django应用程序中创建一个bokeh图,为一名运动员绘制游泳项目图。我正在绘制游泳的持续时间和游泳比赛的日期。其想法是拥有一个绘图,并能够使用SelectBox小部件选择图形上显示的事件。问题是,当我在CallbackJS函数中更改数据源时,图形不会更新,而是变为空白

数据来自表单的事件对象

class Event(models.Model):
    swimmer = models.ForeignKey(Swimmer, on_delete=models.SET_NULL, null=True, blank=True)
    team = models.ForeignKey(Team, on_delete=models.CASCADE, null=True, blank=True)
    name = models.CharField(max_length=50, null=True, blank=True)
    gender = models.CharField(max_length=1, choices=GENDER_CHOICE, null=True, blank=True)
    event = models.CharField(max_length=10, choices=EVENT_CHOICE)
    time = models.DurationField()
    place = models.IntegerField(null=True, blank=True)
    date = models.DateField(null=True)
首先,我当前遍历每个事件17,并列出date datetime.date和time datetime.timedelta字段。未修改的字段分别用于x和y,并且对值进行编辑,主要是将类型转换为字符串以用于悬停工具。如果没有特定事件的数据,则数据源{}条目将设置为无

示例数据:

data_source = {
    'x_50_free': [date(2017,9,7), date(2017,9,8)]
    'y_50_free': [timedelta(seconds=22.96), timedelta(seconds=22.32)]
    'date_50_free': ['9/7/2017', '9/8/2017']
    'time_50_free': ['00:22.96', '00:22.32']
    'x_100_free': [date(2017,9,7)]
    'y_100_free': [timedelta(seconds=49.86)]
    'date_100_free': ['9/7/2017']
    'time_100_free': ['00:49.86']
}
然后,我绘制一条初始线,以便在页面加载时显示一条线

source = ColumnDataSource(data=dict(
    x=data_source['x_'+first_event],
    y=data_source['y_'+first_event],
    date=data_source['date_'+first_event],
    time=data_source['time_'+first_event]
))
plot.line('x', 'y', source=source)
我在回调函数中更新源数据

callback = CustomJS(args=dict(source=source), code="""
    data = %s;
    f = cb_obj.value;

    if (f == "50 Freestyle") {
        source.data['x'] = data.x_50_free;
        source.data['y'] = data.y_50_free;
        source.data['date'] = data.date_50_free;
        source.data['time'] = data.time_50_free;
    } else if (f == "100 Freestyle") {
        source.data['x'] = data.x_100_free;
        source.data['y'] = data.y_100_free;
        source.data['date'] = data.date_100_free;
        source.data['time'] = data.time_100_free;
    }

    ...

    } else if (f == "400 IM") {
        source.data['x'] = data.x_400_im;
        source.data['y'] = data.y_400_im;
        source.data['date'] = data.date_400_im;
        source.data['time'] = data.time_400_im;
    }

    source.change.emit();
""" % json.dumps(data_source, cls=DatetimeEncoder)) # encoder to handle datetimes for x-axis

据我所知,source.change.emit用于更新ColumnDataSource。这似乎是可行的,因为我能够将source.data[]记录到控制台,并看到它根据选择小部件选项进行更新,但绘图本身并不更新,它只是变为空白。如何更新绘图以反映源数据的变化?

您的示例既不简单也不完整。可以立即运行完整的示例。最小的一个会遗漏与您的问题无关的方面。因此,我不确定自己是否理解了一切,但我试着去适应它。以下是一些让您开始学习的代码:

from bokeh.io import show, output_file, output_notebook
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.layouts import column, widgetbox
from bokeh.models import CustomJS, Select

output_file("swim_plot.html")

first_event = "_50_free"
second_event = "_100_free"

data_source = {
    'x': [date(2017,9,3), date(2017,9,4)],
    'y': [0, 0],
    'x_50_free': [date(2017,9,7), date(2017,9,8)],
    'y_50_free': [22.23, 24.34],
    'x_100_free': [date(2017,9,12), date(2017,9,14)],
    'y_100_free': [23.22, 25,12]
}    
source = ColumnDataSource(data=data_source)

callback = CustomJS(args=dict(source=source), code="""
    data = source.data;
    f = cb_obj.value;
    if (f == "_50_free") {
        data['x'] = data.x_50_free;
        data['y'] = data.y_50_free;
    } else if (f == "_100_free") {
        data['x'] = data.x_100_free;
        data['y'] = data.y_100_free;
    }
    source.change.emit();
""")

select = Select(title="Option:", value="default", options=["default",
                first_event, second_event])
select.js_on_change('value', callback)   

plot = figure(plot_width=400, plot_height=400, x_axis_type='datetime')
plot.line('x', 'y', source=source)    
show(column(widgetbox(select),plot))

我在代码中看到的主要问题是ColumnDataSource的定义。当您将所有数据添加到数据目录中时,您只将其中的一部分添加到源中。因此,尝试访问JS回调中丢失的数据将失败

你能不能写一个完整但最简单的例子来说明你在做什么?特别是包括一些模拟数据和您对回调的定义。@mc51是的,就是这么做的!如果您需要更多信息,请告诉我。我觉得我很接近,只是情节本身没有更新的问题。很抱歉这个糟糕的例子,整个事情有点长,我不确定什么可能是相关的,但似乎没有必要包括我以后将要处理的所有内容。我现在能提供什么帮助吗?至于你的答案,为什么你要将“x”和“y”与“x_50_free”、“y_50_free”等分开定义。?我这样定义源代码的原因是在ColumnDataSource中建立键“x”、“y”、“date”和“time”,然后可以在以后更改这些值。我是否必须将所有数据添加到ColumnDataSource以便以后访问它?因为正如我之前所说,当选择被更改并且数据被更改时,我可以将source.data记录到控制台,但是绘图没有更新,所以我最初认为触发绘图更新和无法正确更改数据是一个问题。是的,您必须将数据添加到ColumnDataSource。这就是我最后几句话的意思。