As Dash uses Flask, you should just be able to use the same Flask code you posted. You’ll have to call it inside a callback, as that is during a request context.
You suggest that we could only call flask.request.host_url inside a callback function due to the dependency of a request context.
I have another question
import dash
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
# Here, I want to get this string "http://127.0.0.1:8050/assets/data.pdf"
# But there is no callback binding with this component because it's static resource. In my opinion we should not bind callback to this function which serves static thing
# My question is: Is there any way to get `host_url` without callback context? or I have to create a callback for it?
html.Div(children='URL of assets/data.pdf is ...'),
])
app.run_server()
Actually yes, you can do this inside a layout. The trick is making your app.layout assigned to a function that returns a layout. This way the creation of the layout will be within a request context. The one catch to this is that initial callback validation needs to run the function once before the app loads, which will not be inside a request context. Rather than disabling callback validation, you can detect whether the function is being evaluated within a request context and react accordingly.
This is discussed in the URLs page of the docs, under “Dynamically Create a Layout for Multi-Page App Validation”.
Here’s a simple example illustrating this:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, State, Output
import flask
def make_layout():
# need to detect whether we're in a request context
host = flask.request.host_url if flask.has_request_context() else ''
return html.Div([
html.Div(f"Host: {host}"),
html.Div(id='target'),
dcc.Input(id='my-input', type='text', value=''),
html.Button(id='submit', n_clicks=0, children='Save')
])
app = dash.Dash()
app.layout = make_layout
@app.callback(Output('target', 'children'), [Input('submit', 'n_clicks')],
[State('my-input', 'value')])
def callback(n_clicks, state):
# we are always within a request context here
print(flask.request.host_url)
return "callback received value: {}".format(state)
if __name__ == '__main__':
app.run_server(debug=True)