Hello,
I’m using sample codes shown on
Charming Data
but when I’m modifying CRUD app to be part of mutlipage app it doesn’t work.
callbacks are inactive. Could you advice how to fix this?
it doesn’t matter if I use @app.callback, or just @callback not creating the app on the page9 it still doesn’t work. Thank you in advance!
code for main app is:
from dash import html, dcc
import dash_bootstrap_components as dbc
import dash_auth
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
USERNAME_PASSWORD_PAIRS = [
['JB', '13']
]
app = dash.Dash(__name__, use_pages=True, external_stylesheets=[dbc.themes.SPACELAB])
server = app.server
auth = dash_auth.BasicAuth(app,USERNAME_PASSWORD_PAIRS)
sidebar = dbc.Nav(
[
dbc.NavLink(
[
html.Div(page["name"], className="ms-2"),
],
href=page["path"],
active="exact",
)
for page in dash.page_registry.values()
],
vertical=True,
pills=True,
className="bg-light",
)
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.Div("Sales Report and Analysis",
style={'fontSize':50, 'textAlign':'center'}))
]),
html.Hr(),
dbc.Row(
[
dbc.Col(
[
sidebar
], xs=4, sm=4, md=2, lg=2, xl=2, xxl=2),
dbc.Col(
[
dash.page_container
], xs=8, sm=8, md=10, lg=10, xl=10, xxl=10)
]
)
], fluid=True)
if __name__ == "__main__":
app.run(debug=False, port=8019)
code for page 9 is.
import dash
from dash import Dash, dash_table, dcc, html, Input, Output, callback, State
import plotly.express as px
import dash_bootstrap_components as dbc
import pandas as pd
import dash
from dash.dependencies import Input, Output, State
from dash import dash_table
from dash import dcc, html
import sqlite3
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
dash.register_page(__name__,
path='/page1',
name='Targets',
title='Targerts'
)
server = Flask(__name__)
server.app_context().push()
server.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///books.db"
# Optional: But it will silence the deprecation warning in the
app = dash.Dash(__name__, server=server, suppress_callback_exceptions=True)
app.server.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app.server)
print(db.engine)
class Product(db.Model):
__tablename__ = 'productlist'
Phone = db.Column(db.String(40), nullable=False, primary_key=True)
Version = db.Column(db.String(40), nullable=False)
Price = db.Column(db.Integer, nullable=False)
Sales = db.Column(db.Integer, nullable=False)
def __init__(self, phone, version, price, sales):
self.Phone = phone
self.Version = version
self.Price = price
self.Sales = sales
db.create_all()
conn = sqlite3.connect('instance/books.db')
# Get all table names
tables = pd.read_sql_query("SELECT name from sqlite_master WHERE type='table'", conn)
# Print the table names
print(77777777777777777777777)
print(tables["name"])
print(tables)
df = pd.read_sql_table('productlist', con=db.engine)
print(df)
print(db.engine)
print(77777777777777777777777)
# ------------------------------------------------------------------------------------------------
layout = html.Div([
html.Div([
dcc.Input(
id='adding-rows-name',
placeholder='Enter a column name...',
value='',
style={'padding': 10}
),
html.Button('Add Column', id='adding-columns-button', n_clicks=0)
], style={'height': 50}),
dcc.Interval(id='interval_pg', interval=86400000*7, n_intervals=0), # activated once/week or when page refreshed
html.Div(id='postgres_datatable'),
html.Button('Add Row', id='editing-rows-button', n_clicks=0),
html.Button('Save to PostgreSQL', id='save_to_postgres', n_clicks=0),
# Create notification when saving to excel
html.Div(id='placeholder', children=[]),
dcc.Store(id="store", data=0),
dcc.Interval(id='interval', interval=1000),
# dcc.Graph(id='my_graph')
])
# ------------------------------------------------------------------------------------------------
#
#
@callback(Output('postgres_datatable', 'children'),
[Input('interval_pg', 'n_intervals')])
def populate_datatable(n_intervals):
df = pd.read_sql_table('productlist', con=db.engine)
print(90)
print(df)
return [
dash_table.DataTable(
id='our-table',
columns=[{
'name': str(x),
'id': str(x),
'deletable': False,
} if x == 'Sales' or x == 'Phone'
else {
'name': str(x),
'id': str(x),
'deletable': True,
}
for x in df.columns],
data=df.to_dict('records'),
editable=True,
row_deletable=True,
filter_action="native",
sort_action="native", # give user capability to sort columns
sort_mode="single", # sort across 'multi' or 'single' columns
page_action='none', # render all of the data at once. No paging.
style_table={'height': '300px', 'overflowY': 'auto'},
style_cell={'textAlign': 'left', 'minWidth': '100px', 'width': '100px', 'maxWidth': '100px'},
style_cell_conditional=[
{
'if': {'column_id': c},
'textAlign': 'right'
} for c in ['Price', 'Sales']
]
),
]
#
#
@callback(
Output('our-table', 'columns'),
[Input('adding-columns-button', 'n_clicks')],
[State('adding-rows-name', 'value'),
State('our-table', 'columns')],
prevent_initial_call=True)
def add_columns(n_clicks, value, existing_columns):
if n_clicks > 0:
existing_columns.append({
'name': value, 'id': value,
'renamable': True, 'deletable': True
})
return existing_columns
#
@callback(
Output('our-table', 'data'),
[Input('editing-rows-button', 'n_clicks')],
[State('our-table', 'data'),
State('our-table', 'columns')],
prevent_initial_call=True)
def add_row(n_clicks, rows, columns):
if n_clicks > 0:
rows.append({c['id']: '' for c in columns})
return rows
#
#
# @app.callback(
# Output('my_graph', 'figure'),
# [Input('our-table', 'data')],
# prevent_initial_call=True)
# def display_graph(data):
# # df_fig = pd.DataFrame(data)
# # fig = px.bar(df_fig, x='Phone', y='Sales')
#
# pg_filtered = db.session.query(Product.Phone, Product.Sales)
# phone_c = [x.Phone for x in pg_filtered]
# sales_c = [x.Sales for x in pg_filtered]
# fig = go.Figure([go.Bar(x=phone_c, y=sales_c)])
#
# return fig
#
#
@callback(
[Output('placeholder', 'children'),
Output("store", "data")],
[Input('save_to_postgres', 'n_clicks'),
Input("interval", "n_intervals")],
[State('our-table', 'data'),
State('store', 'data')],
prevent_initial_call=True)
def df_to_csv(n_clicks, n_intervals, dataset, s):
output = html.Plaintext("The data has been saved to your PostgreSQL database.",
style={'color': 'green', 'font-weight': 'bold', 'font-size': 'large'})
no_output = html.Plaintext("", style={'margin': "0px"})
input_triggered = dash.callback_context.triggered[0]["prop_id"].split(".")[0]
if input_triggered == "save_to_postgres":
s = 6
pg = pd.DataFrame(dataset)
pg.to_sql("productlist", con=db.engine, if_exists='replace', index=False)
return output, s
elif input_triggered == 'interval' and s > 0:
s = s - 1
if s > 0:
return output, s
else:
return no_output, s
elif s == 0:
return no_output, s
# @app.callback(Output('placeholder', 'children'),
# [Input('save_to_postgres', 'n_clicks')],
# [State('our-table', 'data')])
# def save_to_db(n_clicks, data):
# if n_clicks > 0:
# # Create the table if it doesn't exist
# db.create_all()
# for row in data:
# new_product = Product(Phone=row['Phone'], Version=row['Version'], Price=row['Price'], Sales=row['Sales'])
# db.session.add(new_product)
# db.session.commit()
# return 'Data saved to database'
if __name__ == '__main__':
app.run_server(debug=True, port=8081)