Инициализация Bokeh AjaxDataSource: обратный вызов источника не получает параметры при инициализации

У меня есть график Bokeh vbar на рисунке, который получает данные из AjaxDataSource через обратный вызов JavaScript. После изменения размера он работает нормально, но при инициализации графика возникает ошибка MultiValueDictKeyError, по-видимому, потому, что моя функция обратного вызова вызывается без передачи ей необходимых GET-параметров. (Ошибка находится в строке Amin = float(request.GET["Amin"]) функции ajax_data).

Как настроить сюжет так, чтобы он правильно инициализировался при первой загрузке?

Вот мой (анонимизированный) код:

def plot(request):
    partnerID = int(request.GET['partnerID'])

    Amin, Amax, Bmax = 0, 50, 0.01

    bokeh_html = get_bokeh_html(Amin, Amax, Bmax)
    c = {"bokeh_html": bokeh_html}

    c["bokeh_js"] = (f'<script src="https://cdn.bokeh.org/bokeh/'
                     f'release/bokeh-{settings.BOKEH_VERSION}.min.js"'
                     f' type="text/javascript"></script>')
    return render(request, 'myapp/plot.html', c)

def get_bokeh_html(Amin, Amax, Bmax):
    fig = bp.figure(
        frame_width=1000,
        frame_height=800,
        title="PLOT",
        tools="box_zoom,wheel_zoom,reset",
        x_axis_label="Abcissa",
        y_axis_label="Data axis",
    )
    fig.toolbar.logo = None

    fig.x_range = Range1d(Amin, Amax)
    fig.y_range = Range1d(0, Bmax)

    source = AjaxDataSource(
        method="GET",
        data_url=reverse("myapp:ajax_data"),
        name="ajax_plot_data_source",
        polling_interval=None,
    )
    r = fig.vbar(
        x="x",
        top="top",
        width=f"width",
        source=source,
    )

    callback = CustomJS(
        args=dict(xr=fig.x_range),
        code="""
        $.ajax({
            url: 'ajax-data',
            data: {
              'Amin': xr.start,
              'Amax': xr.end,
              'partnerID': 2
            },
            success: function (data) {
              var ds = Bokeh.documents[0].get_model_by_name('ajax_plot_data_source');
              ds.data = data;
            }
          });
    """,
    )
    fig.x_range.js_on_change("start", callback)
    fig.legend.click_policy = "hide"

    bokeh_script, bokeh_div = components(fig)
    html = '<div class="bokeh-plot">' + bokeh_script + bokeh_div + "</div>"
    return html

def ajax_data(request):
    Amin = float(request.GET["Amin"])
    Amax = float(request.GET["Amax"])
    partnerID = int(request.GET['partnerID'])

    x, y, dx = get_plot_spec(request, Amin, Amax, partnerID)
    data = {}
    width = dx / 2
    data[f"x"] = list(x.values)
    data[f"top"] = list(y.values)
    data[f"width"] = [width] * len(x)

    response = JsonResponse(data)
    response["Access-Control-Allow-Origin"] = "*"
    response["Access-Control-Allow-Methods"] = "GET"
    response["Access-Control-Max-Age"] = "1000"
    response["Access-Control-Allow-Headers"] = "Content-Type"
    return response

def get_plot_spec(request, Amin, Amax, partnerID):
    df = get_dataframe(Amin, Amax partnerID)
    return df['x'], df[f"y"], dx
Вернуться на верх