Python Dash: функция не должна запускаться, когда n_clicks ‹0 и определена в обратном вызове

Я работаю над приложением plotly dash. У меня есть почти рабочий пример. Единственное, что не работает, это то, что я не могу ограничить функции, определенные в обратных вызовах, чтобы они не запускались при загрузке страницы.

Я попытался добавить проверки для n_clicks внутри обратного вызова, но, похоже, он не работает. Он также запускает функцию без щелчков

Ниже приведен код тире

from datetime import date
import base64
import dash
import plotly
import dash

from dash.dependencies import Input, Output, State
from plotly.graph_objs import *
from datetime import datetime as dt
import dash_html_components as html
import dash_core_components as dcc

import flask
import pandas as pd

server = flask.Flask('app')

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash('app', server=server, external_stylesheets=external_stylesheets)



app.layout = html.Div(style={'backgroundColor': '#EFEAEA', 'margin': '0px', 'padding': '0px'}, children=[
    html.Div([
        html.Div([
            html.Img(src='data:image/png;base64,{}'.format(encoded_image.decode()),
                 style={'width': '200px', 'height': '100px', 'display': 'inline-block', 'float': 'left', 'padding-left': '5px', 'padding-top': '5px'})
        ]),
        html.Div([
            html.Div([
                html.Div([
                    dcc.Dropdown(
                        id='demographics',
                        options=[
                            {'label': 'All 18-49', 'value': '18_39'},
                            {'label': 'Female 25-54', 'value': '25_54 F'},
                            {'label': 'All 25-54', 'value': '25-54'},
                        ],
                        placeholder="Select Demographics",
                    )
                ],
                    style={'width': '30.5%', 'display': 'inline-block', 'padding-right': '10px'}),
                html.Div([
                    dcc.DatePickerRange(
                        id='my-date-picker-range',
                        start_date_placeholder_text="Select a Start Date",
                        end_date_placeholder_text="Select an End Date",
                        min_date_allowed=dt(2018, 1, 1),
                        max_date_allowed=dt(2050, 12, 31),
                        initial_visible_month=dt(2019, 1, 2),
                        style={'width': '600', 'display': 'inline-block', 'padding-right': '10px'}
                    ),
                    html.Div(id='output-container-date-picker-range')
                ],
                    style={'width': '30.3%', 'display': 'inline-block', 'padding-right': '10px', 'position': 'relative'})

            ],
                style={
                'backgroundColor': '#EFEAEA',
                'padding': '5px 10px'}),
            html.Div([
                html.Div([
                    dcc.Dropdown(
                        id='Horsepower',
                        options=[
                            {'label': '200', 'value': 'two_hundred'},
                            {'label': '250', 'value': 'two_hundred_fifty'},
                            {'label': '300', 'value': 'three_hundred'},
                            {'label': '350', 'value': 'three_hundred_fifty'},
                            {'label': '400', 'value': 'four_hundred'}
                        ],
                        placeholder="Select TARP",
                    )
                ],
                    style={'width': '20%', 'display': 'inline-block', 'padding-right': '10px'}),
                html.Div([
                    dcc.Dropdown(
                        id='Kilometers',
                        options=[
                            {'label': '250,000', 'value': 250000, 'type': 'number'},
                            {'label': '500,000', ''value': 500000, 'type': 'number'},
                            {'label': '750,000', 'value': 750000, 'type': 'number'},
                            {'label': '1,000,000', 'value': 1000000, 'type': 'number'},
                        ],
                        placeholder="Select Impressions",
                    )
                ],
                    style={'width': '20%', 'display': 'inline-block', 'padding-right': '10px'}),
                html.Div([
                    dcc.Dropdown(
                        id='Speed',
                        options=[
                            {'label': 'Low', 'value': 50, 'type': 'number'},
                            {'label': 'Average', 'value': 100, 'type': 'number'},
                            {'label': 'High', 'value': 150, 'type': 'number'},
                        ],
                        placeholder="Select Frequency",
                    )
                ],
                    style={'width': '20%', 'display': 'inline-block', 'padding-right': '10px'}),
                html.Div([
                    html.Button('Submit', id='submit_button', type='submit', n_clicks=1,
                                style={'width': '100px', 'height': '34.5px', 'margin-bottom': '8px',
                                       'border-radius': '4px', 'display': 'inline-block', 'background-color': '#2D91C3', 'color': 'white'})
                ],
                    style={'display': 'inline-block', 'padding-bottom': '20px', 'verticalAlign': 'middle'}),
            ], style={
                'backgroundColor': '#EFEAEA',
                'padding': '5px'})
            ], style={'position': 'relative', 'left': '250px'})
        ]),

    html.Div([
        html.Div([
            dcc.Graph(id='example-graph', config={'modeBarButtonsToRemove': ['pan2d', 'lasso2d', 'sendDataToCloud',
                                                                             'select2d', 'autoScale2d', 'resetScale2d',
                                                                             'toggleSpikelines',
                                                                             'hoverClosestCartesian']})
        ],
            style={'width': '49.3%', 'display': 'inline-block', 'border': 'thin grey solid',  'margin-left': '5px',
                   'margin-right': '2.5px', 'margin-top': '5px', 'margin-bottom': '2.5px'}),
        html.Div([
            dcc.Graph(id='example-graph1')
        ],
            style={'width': '49.3%', 'display': 'inline-block', 'border': 'thin grey solid', 'margin-left': '2.5px',
                   'margin-right': '5px', 'margin-top': '5px', 'margin-bottom': '2.5px', 'backgroundColor': '#EFEAEA'})
        ], style={'backgroundColor': '#EFEAEA'}),
    html.Div([
        dcc.Graph(id='graph1')
    ],
        style={'width': '99.2%', 'height': '120%', 'display': 'inline-block', 'border': 'thin grey solid', 'margin-left': '2.5px',
               'margin-right': '5px', 'margin-top': '5px', 'margin-bottom': '2.5px', 'backgroundColor': '#EFEAEA'})
    ])


@app.callback(Output('example-graph1', 'figure'),
              [Input('submit_button', 'n_clicks')],
              [State('my-date-picker-range', 'start_date'),
               State('my-date-picker-range', 'end_date')])

def update_graph(n_clicks, start_date,  end_date):
    if n_clicks > 0:
        df = df_new
        start_date_temp = dt.strptime(start_date, '%Y-%m-%d')
        end_date_temp = dt.strptime(end_date, '%Y-%m-%d')
        start_date_new = start_date_temp.replace(start_date_temp.year - 1)
        end_date_new = end_date_temp.replace(end_date_temp.year - 1)
        end_date_string = end_date_new.strftime('%Y-%m-%d')
        start_date_string = start_date_new.strftime('%Y-%m-%d')
        mask = (df['Date'] >= start_date_string) & (df['Date'] <= end_date_string)
        filtered_df = df.loc[mask]
        trace = Scatter(
            y=filtered_df['Weights'],
            x=filtered_df['Date'],
            line=plotly.graph_objs.scatter.Line(
                color='#42C4F7'
            ),
            hoverinfo='skip',
            error_y=plotly.graph_objs.scatter.ErrorY(
                type='data',
                array=filtered_df['Gender'],
                thickness=1.5,
                width=2,
                color='#B4E8FC'
            ),
            mode='lines'
        )
        layout1 = Layout(
            height=450,
            xaxis=dict(
                showgrid=False,
                showline=False,
                zeroline=False,
                fixedrange=True,
                title='Time Elapsed (sec)'
            ),
            yaxis=dict(
                showline=False,
                fixedrange=True,
                zeroline=False,

            ),
            margin=plotly.graph_objs.layout.Margin(
                t=45,
                l=50,
                r=50
            )
        )

        return Figure(data=[trace], layout=layout1)
    else:
        return {"I am the boss"}

Причина, по которой я предполагаю, что проверки n_clicks не работают, потому что я получаю следующую ошибку

TypeError: strptime() argument 1 must be str, not None

Я считаю, что ошибка связана с приведенным ниже кодом внутри функции, поскольку при первой загрузке страницы start_date не будет типом.

start_date_temp = dt.strptime(start_date, '%Y-%m-%d')

Может ли кто-нибудь помочь решить проблему. Я ожидаю, что при загрузке страницы функция обратного вызова не должна запускаться.

Заранее большое спасибо !!


person Analytics_TM    schedule 12.04.2019    source источник
comment
Для ясности, вы видите эту ошибку при загрузке страницы? Т.е. перед тем, как нажать кнопку отправки в первый раз?   -  person cosmic_inquiry    schedule 12.04.2019
comment
@cosmic_inquiry, да, я вижу ошибку, как только загружаю страницу, прежде чем нажимать кнопку отправки. Когда я ввожу данные в средство выбора даты на передней панели и нажимаю кнопку отправки. Он работает отлично, и графики загружаются отлично. Это единственная ошибка, которую я получаю   -  person Analytics_TM    schedule 13.04.2019


Ответы (1)


Вот твоя проблема:

html.Button('Submit', id='submit_button', type='submit', n_clicks=1,

Вы предварительно установили n_clicks, чтобы иметь значение. Просто удалите эту n_clicks=1 часть, и она загрузит страницу как None. Затем вам нужно будет проверить n_clicks следующим образом (или аналогичным образом):

if n_clicks is not None and n_clicks > 0:

Это сработало для меня и работало, пока не сломалось с моим примером df.

person coralvanda    schedule 13.04.2019
comment
Если вы не возражаете, я спрошу еще кое-что. Есть ли какая-нибудь другая библиотека, кроме dcc.graph. Я пытался использовать электронные диаграммы, но почему-то это не помогало. - person Analytics_TM; 14.04.2019
comment
Извините, но я не знаком с другим, что я мог бы порекомендовать. - person coralvanda; 14.04.2019
comment
Есть еще одна вещь, если вы не возражаете, я спрошу. Я пытался настроить свой диапазон датпикера. Однако я не смог этого сделать. Я искал повсюду в Интернете, однако я не нашел ни одной статьи, в которой говорилось бы о том, как настроить диапазон выбора даты. Могу ли я настроить диапазон выбора даты? Я обновил макет своего приложения, если вы хотите посмотреть. Я не хотел задавать еще один вопрос только по этому поводу. - person Analytics_TM; 14.04.2019
comment
Возможно, стоит задать еще один вопрос, потому что вам придется более подробно объяснить, как вы хотите его настроить. Я думаю, вы уже ознакомились с ними, но вот документы прямо в кейс. - person coralvanda; 14.04.2019
comment
Конечно, сделал бы это. Я просмотрел эту документацию, но ничего не сказал о ее настройке по ширине и высоте. - person Analytics_TM; 15.04.2019
comment
Хм, у него есть атрибут style. Я не играл с этим компонентом, но некоторые CSS могут заставить его выглядеть так, как вы хотите. - person coralvanda; 15.04.2019
comment
Я пробовал использовать атрибут стиля, но не смог его исправить. а может быть, я поступаю неправильно. - person Analytics_TM; 15.04.2019
comment
Я тоже использовал CSS, но почему-то он не меняет стиль диапазона датпикера. - person Analytics_TM; 15.04.2019