ImportError: cannot import name 'app' from 'app' - python

I'm fairly new to dash and I'm trying to follow along some of the more advanced guides (link: here) that look at multi page dashboards but seem to be falling over at every hurdle along the way.
I've managed to create my virtual environment install the required packages and I've just created the 'app.py' file but when I create and run the 'index.py' file I'm seeing the following error:
ImportError: cannot import name 'app' from 'app'
The app.py file I'm running was created with the following code:
import dash
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
server = app.server
#app.config.suppress_callback_exceptions = True ####<-- tutorial said to run this line but as suppress was giving me errors I removed it
The 'index.py' file I'm running looks like:
from app import app
from app import server
import dash_html_components as html
import dash_core_components as dcc
app.layout = html.Div([html.H1('Dash Demo Graph',
style={
'textAlign': 'center',
"background": "yellow"}),
dcc.Graph(
id='graph-1',
figure={
'data': [
{'x': [1, 2, 3, 4, 5, 6, 7], 'y': [10, 20, 30, 40, 50, 60, 70], 'type': 'line', 'name': 'value1'},
{'x': [1, 2, 3, 4, 5, 6, 7], 'y': [12, 22, 36, 44, 49, 58, 73], 'type': 'line', 'name': 'value2'}
],
'layout': {
'title': 'Simple Line Graph',
}
}
),
], style={
"background": "#000080"}
)
if __name__ == '__main__':
app.run_server(debug=True)
I'm on a Windows machine using Jupyter Lab and python 3.8, the directory I'm running the code out of has the following folders and files in:
.ipynb_checkpoints
__pycache__
env
app.py
index.py
Any help on how I resolve this error would be much appreciated.

Related

Export Plotly Dash datatable output to a CSV by clicking download link

Hi Anyone able to help advise?
I have an issue trying to export the data being populated from data table filtered from drop down selection upon clicking on download link to a CSV file.
Error gotten after clicking on the Download Link
csv_string = dff.to_csv(index=False, encoding='utf-8')
AttributeError: 'str' object has no attribute 'to_csv'
And the file that was downloaded is a file containing html code.
Code snippets below
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output,State
import plotly.graph_objs as go
import dash_table
import dash_table_experiments as dt
from urllib.parse import quote
import flask
import pandas as pd
import numpy as np
import pyodbc
app.layout = html.Div([
html.H3("Sales Summary Report"),
dcc.Graph(
figure={
"data": [
{
"x": df["Sales_RANGE"],
"y": df['count'],
"name":'No of Cust',
"type": "bar",
"marker":{'color':'rgba(26, 118, 255, 0.5)',
#'line':{
# 'color':'rgb(8,48,107)',
# 'width':1.5,
# }
}
}
],
"layout": {
"xaxis": {"automargin": True},
"yaxis": {
"automargin": True,
# "title": {"text": column}
},
"height": 250,
"margin": {"t": 10, "l": 10, "r": 10},
},
},
)
,
html.Label(["Select Sales range to view",
dcc.Dropdown(
id="SalesRange",
style={'height': '30px', 'width': '55%'},
options=[{'label': i,
'value': i
} for i in Sales_Range_Options],
value='All'
)
]),
#TABLE
html.H5("Details"),
html.Div(id='detailsresults') ,
html.A('Download Data',
id='download-link',
download="rawdata.csv",
href="",
target="_blank"
)
])
def generate_table(dataframe):
'''Given dataframe, return template generated using Dash components
'''
return html.Div( [dash_table.DataTable(
#id='match-results',
data=dataframe.to_dict('records'),
columns=[{"name": i, "id": i} for i in dataframe.columns],
editable=False
),
html.Hr()
])
#app.callback(
Output('detailsresults', 'children'),
[
Input('SalesRange', 'value'),
]
)
def load_results(SalesRange):
if SalesRange== 'All':
return generate_table(df)
else:
results = df[df['SALES_RANGE'] == SalesRange]
return generate_table(results)
#app.callback(
dash.dependencies.Output('download-link', 'href'),
[dash.dependencies.Input('SalesRange', 'value')])
def update_download_link(SalesRange):
dff = load_results(SalesRange)
csv_string = dff.to_csv(index=False, encoding='utf-8')
csv_string = "data:text/csv;charset=utf-8,%EF%BB%BF" + quote(csv_string)
return csv_string
CSV export is officially supported by dash_table.DataTable. You simply need to specify export_format='csv' when you build the table:
dash_table.DataTable(
id="table",
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict("records"),
export_format="csv",
)
Here's a complete example app.py that you can run:
import dash
import dash_table
import dash_html_components as html
import pandas as pd
df = pd.DataFrame(
[
["California", 289, 4395, 15.3, 10826],
["Arizona", 48, 1078, 22.5, 2550],
["Nevada", 11, 238, 21.6, 557],
["New Mexico", 33, 261, 7.9, 590],
["Colorado", 20, 118, 5.9, 235],
],
columns=["State", "# Solar Plants", "MW", "Mean MW/Plant", "GWh"],
)
app = dash.Dash(__name__)
server = app.server
app.layout = dash_table.DataTable(
id="table",
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict("records"),
export_format="csv",
)
if __name__ == "__main__":
app.run_server(debug=True)
You will see a button above the table:
I believe your answer is like the following:
#app.server.route('/dash/urlToDownload')
def download_csv():
return send_file('output/downloadFile.csv',
mimetype='text/csv',
attachment_filename='downloadFile.csv',
as_attachment=True)
You may take a look at this link for more information:
Allowing users to download CSV on click

Changing from scattermapbox to densitymapbox causes error

I was looking for a solution to this issue I encountered. There is a question almost similar to mine in plotly community (https://community.plot.ly/t/problem-with-densitymapbox-chart-type/28517), but still haven’t found a resolution. My dropdown menu consists of scattermapbox and densitymapbox as i wanted to juggle between these. However, when changing from scattermapbox to densitymapbox, it results to the image below:
densitymapbox after scattermapbox format
import dash
import copy
import pathlib
import dash
import numpy as np
import math
import datetime as dt
import pandas as pd
from dash.dependencies import Input, Output, State, ClientsideFunction
import dash_core_components as dcc
import dash_html_components as html
import dash_table
import plotly.graph_objs as go
# get relative data folder
PATH = pathlib.Path(__file__).parent
DATA_PATH = PATH.joinpath("data").resolve()
external_scripts = [
‘https://cdn.plot.ly/plotly-1.39.1.min.js’
]
external_stylesheets = [
‘https://codepen.io/etpinard/pen/wxwPXJ’
]
app = dash.Dash(
__name__,
external_scripts=external_scripts,
external_stylesheets=external_stylesheets
)
server = app.server
# Load data
df = pd.read_excel("Clean_TR(6.8.19).xlsx")
group_name = df['gname'].unique()
mapbox_access_token = <your token>
app.layout = html.Div(
[
dcc.Store(id = 'aggregate_data'),
dcc.Dropdown(
id = 'map_plot',
options = [{'label':i, "value":i} for i in ['Scatter', 'Density']],
value = ['Scatter']
),
dcc.Graph(id = 'mindanao-map')
]
)
#app.callback(
Output('mindanao-map', 'figure'),
[Input('map_plot', 'value')]
)
def update_map(map_plot):
if map_plot == "Density":
maptype = 'densitymapbox'
else:
maptype = 'scattermapbox'
return {
'data' : [{
'lat':df['latitude'],
'lon':df['longitude'],
'marker':{
'color': df['freq'],
'size': 8,
'opacity': 0.6
},
'customdata': df['idno'],
'type': maptype
}],
'layout': {
'mapbox': {
'accesstoken': mapbox_access_token,
'style':"light",
'center': dict(lon=123.30, lat= 7.50),
'zoom':'6',
},
'hovermode': 'closest',
'margin': {'l': 0, 'r': 0, 'b': 0, 't': 0}
}
}
if __name__ == "__main__":
app.run_server(debug=True)
But whenever I swap out the if-else ordering, i.e,
if map_plot == "Scatter":
maptype = 'scattermapbox'
else:
maptype = 'densitymapbox'
it results to density map showing, but scatter will not.
Do I need to separate these two instead of if-else? Any inputs will do. Thank you for your time!
This is a Plotly.js bug, and I've filed a report here: https://github.com/plotly/plotly.js/issues/4285
Edit: this bug is fixed in recent versions of Plotly.js and Plotly.py and Dash.

How do I display a website written in Dash as a static PDF (Python)?

I want to export the site I've made in dash into a static PDF. Here is the code for my site (it's just a chart with 3 columns):
import dash
import dash_core_components as dcc
import dash_html_components as html
import pdfkit
from flask import Flask, render_template, make_response
app = dash.Dash()
app.layout = html.Div(
className="three columns",
children=html.Div([
dcc.Graph(
id='right-top-graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [3, 1, 2],
'type': 'bar'
}],
'layout': {
'height': 400,
'margin': {'l': 10, 'b': 20, 't': 0, 'r': 0}
}
}
),
])
)
app.css.append_css({
'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'
})
if __name__ == '__main__':
app.run_server(debug=True)
I tried using pdfkit by adding this code to my script, but it didn't work (received an error telling me that render_template() takes 1 positional argument but 2 were given):
rendered = render_template('pdf_template.html',app)
pdf = pdfkit.from_string(rendered, False)
response = make_response(pdf)
response.headers['Content-Type'] = 'application/pdf'
response.headers['Content-Disposition'] = 'attachment; filename=output.pdf'
Does anyone have any idea as to how I can convert my dash site into a PDF?
Thanks in advance.
You can use the print function of whatever browser you are using (usually control + p) and save it as PDF if all you are looking for is the static PDF file.
If you want more enhanced functionality you can add a print to PDF button like the one in one of the dash examples. It uses a js file to invoke the browser print functionality, see more detail. This way you can also use CSS to define the way the PDF output looks
The problem with using the python file to generate pdf directly is that dash only creates a JSON representation of the layout tree which is then assembled in the browser itself, see more.
You can use pdfkit in the following way:
import pdfkit
pdfkit.from_url('http://local.dash.site', 'out.pdf')
The big difference from what you posted is that you could use the local web server to render the page.
As an alternative, you could also use https://wkhtmltopdf.org/
This is the lib underneath pdfkit.
You can use the directions from the following link to create pdf:
http://flask.pocoo.org/snippets/68/
render_template accepts only one positional arguments, the rest must be keyword arguments.
render_template takes only one positional argument.
Can you try below?
options = {
'margin-top': '0.15in',
'margin-right': '0.15in',
'margin-bottom': '0.2in',
'margin-left': '0.15in',
'encoding': "UTF-8",
}
css = 'path to your .css file'
html = render_template('a_html.html')
pdf = pdfkit.from_string(html, False, options=options, css=css)
Have you tried running your script in the following way (I've just pasted the pdf creation part of your script into where the dash site is rendered):
import dash
import dash_core_components as dcc
import dash_html_components as html
import pdfkit
from flask import Flask, render_template, make_response
app = dash.Dash()
app.layout = html.Div(
className="three columns",
children=html.Div([
dcc.Graph(
id='right-top-graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [3, 1, 2],
'type': 'bar'
}],
'layout': {
'height': 400,
'margin': {'l': 10, 'b': 20, 't': 0, 'r': 0}
}
}
),
])
)
app.css.append_css({
'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'
})
rendered = render_template('pdf_template.html',app)
pdf = pdfkit.from_string(rendered, False)
response = make_response(pdf)
response.headers['Content-Type'] = 'application/pdf'
response.headers['Content-Disposition'] = 'attachment; filename=output.pdf'
if __name__ == '__main__':
app.run_server(debug=True)

Multi-Page Dash Application

I'm trying to build a multi page Dash App. When I run the following code, everything works except it won't route to my /dash_1 or /dash_2 urls. Was wondering if someone could help me out.
My structure looks like this:
dash-project/
app1/
app.py
app2/
app.py
server.py
run.py
My run.py code is
from app import server as application
from app import app
import app_1.dash_1
import app_2.dash_2
My app.py code is:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from werkzeug.wsgi import DispatcherMiddleware
import os
import pandas as pd
import dash
import flask
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
from analysis import *
server=flask.Flask(name)
app = dash.Dash(name)
app.config.suppress_callback_exceptions = True
app.css.append_css({
‘external_url’: ‘https://codepen.io/chriddyp/pen/bWLwgP.css’
})
My dash_1.py code is:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
from analysis import *
from app import app, server
app = dash.Dash(name='dash_1', sharing=True,
url_base_pathname='/dash_1', csrf_protect=False)
app.config['suppress_callback_exceptions']=True
df = pd.read_csv('/Users/ds/app_1/main.csv')
layout = html.Div([
dcc.Graph(
id='Senators ',
figure={
'data': [
go.Scatter(
x=df[df['candidate'] == i]
['contributor_individual'],
y=df[df['candidate_name'] == i]['contributor'],
#z=df[df['candidate_name'] == i]['contributor'],
text=df[df['candidate_name'] == i]['contributorl'],
mode='markers',
opacity=0.7,
marker={
'size': 15,
'line': {'width': 0.5, 'color': 'white'}
},
name=i
) for i in df.candidate_name.unique()
],
'layout': go.Layout(
xaxis={'title': 'Contributor '},
yaxis={'title': 'Contributor '},
#margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
#legend={'x': 0, 'y': 1},
hovermode='closest'
)
}
)
])
layout = html.Div(children=[
html.H1(children='Senators '),
html.Div(children='''
God Bless.
'''),
dcc.Graph(
id='main.csv',
figure={
'data': [
{'x':df['candidate'], 'y': df['sectorl'], 'type': 'bar'},
{'x':df['candidate'], 'y': df['industry'], 'type': 'bar'},
{'x':df['candidate'], 'y': df['contributor'], 'type': 'bar'},
],
'layout': {
'title': 'Let Them Eat...'
}
}
)
])
My dash_2.py code is
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
from app import app, server
app = dash.Dash(name='dash_2', sharing=True,
url_base_pathname='/dash_2', csrf_protect=False)
app.config['suppress_callback_exceptions']=True
df = pd.read_csv('/Users/ds/app_2/slice.csv')
layout = html.Div(children=[
html.H1(children='Bars'),
html.Div(children='''
One Bite....
'''),
dcc.Graph(
id='slice.csv',
figure={
'data': [
{'x':df['Slice'], 'y': df['Score'], 'type': 'bar'},
],
'layout': {
'title': 'Bars'
}
}
)
])
Any help would be greatly appreciated - I can't seem to wrap my head around this - Thanks!
You need to pass your flask app to your Dash instance.
Like this.
app = dash.Dash(__name__, server=server)
So try importing server and include it as a parameter in your Dash instances in app1 and app2.
Like so:
from app import server
app = dash.Dash(name='dash_1', sharing=True,
url_base_pathname='/dash_1', csrf_protect=False, server=server)
app = dash.Dash(name='dash_2', sharing=True,
url_base_pathname='/dash_2', csrf_protect=False, server=server)
Hope it helps.
#Franrey Saycon is completely right. You were importing too many things. In case this is helpful to anyone, I created a tutorial that shows how to build a multipage Dash application, with explanations on folder/file structure and library imports.

Plotly figure hide and display

I have a problem with hiding and showing a graph in the Python framework, Dash.
I define a new graph:
html.Div([
dcc.Graph(id = 'graph'),
],),
After I update my trace data with a callback function I return it and it is shown in the graph, but if nothing is selected from my dropdown menu I do
if not input or input == []:
return {'display': 'none'}
so that my graph is not shown, but it doesn't work for some reason.
Is there a workaround?
Thank you in advance
You can set the id element for the Div holding your graph and hide the whole div by using #app.callback on the style element.
html.Div(id="graph-container", children= [
dcc.Graph(id = 'graph'),
]),
#app.callback(Output('graph-container', 'style'), [Input('input_widget','value')])
def hide_graph(input):
if input:
return {'display':'block'}
else:
return {'display':'none'}
To see this code in action you can test out my code:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash()
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Div(children='''
Dash: A web application framework for Python.
'''),
html.Label("Show?"),
dcc.Dropdown(
id="my-input",
options = [
{'label':'Yes', 'value':True},
{'label':'No', 'value':False}
],
value = True
),
html.Div(
id="graph-container",
children = [
dcc.Graph(
id='example-graph',
figure={
'data': [
{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
{'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
],
'layout': {
'title': 'Dash Data Visualization'
}
}
)
])
])
#app.callback(Output('graph-container', 'style'), [Input('my-input', 'value')])
def hide_graph(my_input):
if my_input:
return {'display':'block'}
return {'display':'none'}
if __name__ == '__main__':
app.run_server(port=8125, debug = True)
Note I used the following versions:
python 3.6.4
dash 0.21.0
dcc 0.22.1
html 0.10.0
Thanks lwileczek for the answer. I wanted to provide an update as the code needs a few minor tweaks to work in the following environment:
python 3.7.4
plotly 4.1.1
dash 1.2.0
dcc 1.1.2
html 1.0.1
When I copied lwileczek's code into the above environment, dash through an error about passing a bad argument into the dropdown. After a couple of moments of trial and error, I was able to make the code work if I changed the values in the dropdown to strings and modified the conditional in the callback so that it was doing a string comparison as opposed to expecting the value to be a boolean.
The code for the dropdown looks like:
dcc.Dropdown(
id = 'my-input',
options = [
{'label':'Yes', 'value':'Yes'},
{'label':'No', 'value':'No'}
],
value='Yes'
),
The code for the conditional in the callback becomes:
if my_input == 'Yes':
return {'display': 'block'}
return {'display': 'none'}
(This should probably be a comment, but I don't have enough points to post a comment)

Categories