Quantcast
Channel: 🎛️ Dash - Plotly Community Forum
Viewing all articles
Browse latest Browse all 6271

Python Plotly Dash with Flask Login: How to properly place @callback?

$
0
0

I’m trying to build a Dash app in Flask following this example: openDashAuth/dashboard.py at main · seanmajorpayne/openDashAuth · GitHub

import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
from app.auth import routes
from app.models import User


def create_dashboard(server):
    """Create a Plotly Dash dashboard embedded within Flask"""
    dash_app = dash.Dash(
        server=server,
        routes_pathname_prefix="/dashapp/",
        external_stylesheets=[dbc.themes.CERULEAN],
    )

    dash_app.layout = html.Div(
        children=[
            html.Div(
                [
                    html.Div(
                        [
                            html.H1(id="my-header", className="text-center"),
                        ],
                        className="col-md-12",
                    )
                ],
                className="row",
            ),
            html.A("Login", id="login-link", href="/login"),
            html.Div(id="my-div", className="text-center"),
            html.Button(
                id="submit-button-state",
                n_clicks=1,
                children="Submit",
                style={"display": "none"},
            ),
        ]
    )

    @dash_app.callback(
        [
            Output(component_id="my-header", component_property="children"),
            Output(component_id="my-div", component_property="children"),
            Output(component_id="login-link", component_property="style"),
        ],
        [Input(component_id="submit-button-state", component_property="n_clicks")],
    )
    def get_user_name(n_clicks):
        """
        The dashboard only loads if a user is authenticated
        """
        if routes.get_user().is_authenticated:
            welcome_msg = "Welcome back, " + routes.get_user().username
            user_data = load_data()
            link_style = {"display": "none"}
            return welcome_msg, user_data, link_style
        return "Your Princess is in another castle", ""

    def load_data():
        """
        The user's data is pulled from a database. As the user has already been
        authenticated, the 'current_user' from 'flask_login' is used within a database
        query, ensuring that the correct user's data is loaded. This is the key to
        having multiple user authentication with dedicated views for each user.
        """
        x = []
        y = []
        u = routes.get_user()
        data = u.data_for_user.all()
        for d in data:
            x_data = [d.x1, d.x2, d.x3]
            y_data = [d.y1, d.y2, d.y3]
        return html.Div(
            [
                html.Div(
                    [
                        dcc.Graph(
                            id="client-data",
                            figure={
                                "data": [
                                    {
                                        "x": x_data,
                                        "y": y_data,
                                        "type": "scatter",
                                        "name": "Data",
                                    }
                                ],
                                "layout": {
                                    "title": "Customer Data",
                                    "plot_bgcolor": "#252e3f",
                                    "paper_bgcolor": "#252e3f",
                                    "font": dict(color="#FFFFFF"),
                                    "xaxis": dict(
                                        title="x axis",
                                        color="#98FB98",
                                    ),
                                    "yaxis": dict(title="y axis", color="#98FB98"),
                                    "line": dict(color="#98FB98"),
                                },
                            },
                        )
                    ],
                    className="col-md-8",
                )
            ],
            className="row justify-content-center",
        )

    return dash_app.server

I manage to get data and view my dashboard. But a problem I do not understand is where to place @callback ( in def load_data()).

My try:

import pandas as pd
import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
from dash.dependencies import Output, Input, State
import plotly.express as px
import base64
from app.auth import routes
from app.models import User


def create_dashboard(server):
    """Create a Plotly Dash dashboard embedded within Flask"""
    dash_app = dash.Dash(
        server=server,
        routes_pathname_prefix="/dashapp/",
        external_stylesheets=[dbc.themes.CERULEAN],
    )

    dash_app.layout = html.Div(
        children=[
            html.Div(
                [
                    html.Div(
                        [
                            html.H1(id="my-header", className="text-center"),
                        ],
                        className="col-md-12",
                    )
                ],
                className="row",
            ),
            html.A("Login", id="login-link", href="/login"),
            html.Div(id="my-div", className="text-center"),
            html.Button(
                id="submit-button-state",
                n_clicks=1,
                children="Submit",
                style={"display": "none"},
            ),
        ]
    )

    @dash_app.callback(
        [
            Output(component_id="my-header", component_property="children"),
            Output(component_id="my-div", component_property="children"),
            Output(component_id="login-link", component_property="style"),
        ],
        [Input(component_id="submit-button-state", component_property="n_clicks")],
    )
    def get_user_name(n_clicks):
        """
        The dashboard only loads if a user is authenticated
        """
        if routes.get_user().is_authenticated:
            welcome_msg = "Welcome back, " + routes.get_user().username
            user_data = load_data()
            link_style = {"display": "none"}
            return welcome_msg, user_data, link_style
        return "Your Princess is in another castle", ""



    def load_data():
        """
        The user's data is pulled from a database. As the user has already been
        authenticated, the 'current_user' from 'flask_login' is used within a database
        query, ensuring that the correct user's data is loaded. This is the key to
        having multiple user authentication with dedicated views for each user.
        """
        u = routes.get_user()
        data = u.data_for_user.all()
        df= pd.DataFrame([(d.month, d.id_user, d.shop, d.amount) for d in data],
                          columns=([('month', 'id_user', 'shop', 'amount'])

        # Logo
        logo_png = "image.png"
        logo_base64 = base64.b64encode(open(logo_png, 'rb').read()).decode('ascii')


        # SlicerMonth
        Month_Selector = dcc.Dropdown(id='Month_dropdown',
                                      options=[{'label': i, 'value': i}
                                               for i in df.sort_values(by=['Month'], ascending=False)[
                                                   'Month Name'].unique()],
                                      placeholder="Select Month",
                                      value=df.sort_values(by=['Month'], ascending=False)['Month Name'].unique()[
                                          0],
                                      searchable=False
                                      )

        # Layout
        dash_app.layout = html.Div([
            # Row 1
            dbc.Row([
                # Col 1
                dbc.Col(html.Img(Image.png)),
                # Col 2
                dbc.Col(html.H1("Text")),

                # Col 3
                dbc.Col(html.Div(Month_Selector)),
        # Row 2
            dbc.Row(
                dbc.Col([dcc.Graph(id='sales_subplot')], width=12)),

        ],
            style={'margin-left': '80px',
                   'margin-right': '80px'}
        )


        # Callbacks
        @dash_app.callback(
            Output(component_id='sales_subplot', component_property='figure'),
            Input(component_id='Month_dropdown', component_property='value')
        )

        def update_graph(selected_month):
            # Filtered Data

     
            filtered_df = df[(df['month'] == selected_month)]

            fig = px.bar(filtered_df,x="month",y="amount")


            return fig


    return dash_app.server

The location where I put @callback in a dashboard works, but a user does not change even when another user logs in. Only after disconnecting an app and re-run, it change. When I try to put before function def load_data (): then it does not work at all…

But where does it need to be placed correctly?

2 posts - 2 participants

Read full topic


Viewing all articles
Browse latest Browse all 6271

Trending Articles