{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# FastAPI + Dash\n", "\n", "首先定义 Dash 子应用:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# dashapp.py\n", "import dash\n", "from dash.dependencies import Input, Output\n", "from dash import dcc, html\n", "import pandas as pd\n", "\n", "\n", "def create_dash_app(requests_pathname_prefix: str = None) -> dash.Dash:\n", " df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/hello-world-stock.csv')\n", "\n", " app = dash.Dash(__name__, requests_pathname_prefix=requests_pathname_prefix)\n", " app.scripts.config.serve_locally = False\n", " dcc._js_dist[0]['external_url'] = 'https://cdn.plot.ly/plotly-basic-latest.min.js'\n", "\n", " app.layout = html.Div([\n", " html.H1('Stock Tickers'),\n", " dcc.Dropdown(\n", " id='my-dropdown',\n", " options=[\n", " {'label': 'Tesla', 'value': 'TSLA'},\n", " {'label': 'Apple', 'value': 'AAPL'},\n", " {'label': 'Coke', 'value': 'COKE'}\n", " ],\n", " value='TSLA'\n", " ),\n", " dcc.Graph(id='my-graph')\n", " ], className=\"container\")\n", "\n", " @app.callback(Output('my-graph', 'figure'),\n", " [Input('my-dropdown', 'value')])\n", " def update_graph(selected_dropdown_value):\n", " dff = df[df['Stock'] == selected_dropdown_value]\n", " return {\n", " 'data': [{\n", " 'x': dff.Date,\n", " 'y': dff.Close,\n", " 'line': {\n", " 'width': 3,\n", " 'shape': 'spline'\n", " }\n", " }],\n", " 'layout': {\n", " 'margin': {\n", " 'l': 30,\n", " 'r': 20,\n", " 'b': 30,\n", " 't': 20\n", " }\n", " }\n", " }\n", " return app" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "主应用:\n", "\n", "```python\n", "from fastapi import FastAPI, Request\n", "from fastapi.middleware.wsgi import WSGIMiddleware\n", "from dashapp import create_dash_app\n", "\n", "app = FastAPI()\n", "\n", "\n", "@app.get(\"/\")\n", "def read_main():\n", " return {\n", " \"routes\": [\n", " {\"method\": \"GET\", \"path\": \"/\", \"summary\": \"Landing\"},\n", " {\"method\": \"GET\", \"path\": \"/status\", \"summary\": \"App status\"},\n", " {\"method\": \"GET\", \"path\": \"/dash\",\n", " \"summary\": \"Sub-mounted Dash application\"},\n", " ]\n", " }\n", "\n", "\n", "@app.get(\"/status\")\n", "def get_status():\n", " return {\"status\": \"ok\"}\n", "\n", "\n", "dash_app = create_dash_app(requests_pathname_prefix=\"/dash/\")\n", "app.mount(\"/dash\", WSGIMiddleware(dash_app.server))\n", "\n", "\n", "if __name__ == \"__main__\":\n", " import uvicorn\n", " uvicorn.run(app, port=8001)\n", "```" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "渲染结果:\n", "\n", "![主页](images/index.png)\n", "![Dash](images/dashapp.png)\n" ] } ], "metadata": { "kernelspec": { "display_name": "py310", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.6" }, "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "7e468feb35f514aafce3cc952fb1f3b43bab876fc14f6450ea05924ae7e4a934" } } }, "nbformat": 4, "nbformat_minor": 2 }