如何使用FastAPI后端的JSON响应在前端使用Chart.js创建图表?[duplicate]

w1jd8yoj  于 2022-11-06  发布在  Chart.js
关注(0)|答案(2)|浏览(204)

此问题在此处已有答案

How do I capture response of form.submit(20个答案)
8个月前关门了。
1.我有一个HTML页面正在使用FastAPI呈现:

@app.get("/index", response_class=HTMLResponse)
 def write_home(request: Request):
 return templates.TemplateResponse("index.html", {"request": request})

Rendered HTML
上面的HTML有一个表单的Submit按钮,它将导致端点\SWP的POST请求

<form id="generate" action="swp" method="post" enctype="multipart/form-data">

1.它的工作方式就像我需要的那样--它将数据发布到我的Python计算器应用程序,后者返回一个JSON响应:
Output from Py App
1.通过将JSON文件保存在 * 本地硬盘 * 上,我可以编写JavaScript代码,该代码可以读取其数据并通过Chart.js创建一个图表。我使用了Fetch API,然后使用了对象数组:

const API_URL = "./Example_Response.json";
 async function createChartAndTable() {
 let ResponseFromAPI = await fetch(API_URL);
 let JSON_Res = await ResponseFromAPI.json();
 let JSON_Data1 = JSON.parse(JSON_Res.output.data);

From locally saved JSON file
1.现在,我完全困惑于如何使用Python应用程序http://127.0.0.1:8000/swpStep2)的Live JSON结果,然后将其呈现为步骤1到http://127.0.0.1:8000/index中生成的HTML,就像我在步骤3中使用本地存储的JSON文件所做的那样。
注意:不涉及数据库。
如有任何指导和帮助,不胜感激。

hsgswve4

hsgswve41#

选项1

通过HTML表单发布请求,然后让API将您重定向到一个新页面(Jinja2Template),在那里您可以读取数据并显示图表。正如@tiangolo在这里发布的,当执行RedirectResponsePOST请求路由到GET请求路由时,response status code has to changestatus_code=status.HTTP_303_SEE_OTHER(下面的示例就是这样做的)。

**更新:**此处不需要重定向。您可以像往常一样呈现模板:

@app.post("/submitUsingForm", response_class=HTMLResponse)
def submitUsingForm(request: Request, input1: str = Form(...), input2: str = Form(...)):
    return templates.TemplateResponse("chart.html", {"request": request, "json_data": json_data})

选项2

使用Fetch API发布请求,接收JSON数据并在同一页上显示图表。
下面给出的示例演示了这两个选项(出于本演示的目的,使用的数据是示例数据;您可以根据需要更改/处理它们)。

应用程序.py

from fastapi import FastAPI, Request, status, Form
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi.responses import RedirectResponse

app = FastAPI()

templates = Jinja2Templates(directory="templates")
json_data = {"jsonarray": [{"name": "Joe", "age": 32}, {"name": "Tom", "age": 34}]}

@app.get("/chart", response_class=HTMLResponse)
def get_chart(request: Request):
    return templates.TemplateResponse("chart.html", {"request": request, "json_data": json_data})

@app.post("/submitUsingFetch")
def submitUsingFetch(request: Request, input1: str = Form(...), input2: str = Form(...)):
    return json_data 

@app.post("/submitUsingForm", response_class=HTMLResponse)
def submitUsingForm(request: Request, input1: str = Form(...), input2: str = Form(...)):
    #redirect_url = request.url_for('get_chart')
    #return RedirectResponse(redirect_url, status_code=status.HTTP_303_SEE_OTHER)
    return templates.TemplateResponse("chart.html", {"request": request, "json_data": json_data}) 

@app.get("/", response_class=HTMLResponse)
def home(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

模板/索引.html

<!DOCTYPE html>
<html>
   <head>
      <title> Home</title>
      <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
      <script>
         function send_request() {
            const formElems = document.getElementById('my_form');
            var formData = new FormData(formElems);
            const url = "http://127.0.0.1:8000/submitUsingFetch";
            fetch(url, {
                method: 'POST',
                headers: {'Accept': 'application/json'},
                body: formData
                }).then(resp => {
                    return resp.json();
                }).then(body => {
                    display_chart(body)
                }).catch(error => {
                    console.error(error);
                });
         }

         function display_chart(json_data) {
            var labels = json_data.jsonarray.map(function(e) {return e.name;});
            var data = json_data.jsonarray.map(function(e) {return e.age;});
            const ctx = document.getElementById('myChart');
            var config = {
               type: 'line',
               data: {
                  labels: labels,
                  datasets: [{
                     label: 'Graph Line',
                     data: data,
                     backgroundColor: 'rgba(0, 119, 204, 0.3)'
                  }]
               }
            };

            var chart = new Chart(ctx, config);
         }
      </script>
   </head>
   <body>
      <form action="/submitUsingForm"  method='post' id='my_form'>
         <label>Input 1:</label><br>
         <input type="text" id="input1" name="input1" value="0"><br>
         <label>Input 2:</label><br>
         <input type="text" id="input2" name="input2" value="0"><br>
         <input type="submit" value="Submit using Form">
         <input type="button" value="Submit using Fetch" onclick="send_request()">
      </form>
    <canvas id="myChart"></canvas>
   </body>
</html>

模板/图表.html

<html>
   <head>
      <head>
         <title> Chart</title>
         <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
         <script>
            function display_chart(){
                var json_data = {{json_data|tojson}};
                var labels = json_data.jsonarray.map(function(e) {return e.name;});
                var data = json_data.jsonarray.map(function(e) {return e.age;});
                const ctx = document.getElementById('myChart');
                var config = {
                   type: 'line',
                   data: {
                      labels: labels,
                      datasets: [{
                         label: 'Graph Line',
                         data: data,
                         backgroundColor: 'rgba(0, 119, 204, 0.3)'
                      }]
                   }
                };

                var chart = new Chart(ctx, config);
            }
         </script>
   </head>
   <body onload="display_chart()">
    <canvas id="myChart"></canvas>
   </body>
</html>
sq1bmfud

sq1bmfud2#

让它与下面的代码一起工作。像@傻瓜在他/她的一条评论中建议的技巧

document.forms['myFormId'].addEventListener('submit', (event) => {
    event.preventDefault();
    // TODO do something here to show user that form is being submitted
    fetch(event.target.action, {
        method: 'POST',
        body: new URLSearchParams(new FormData(event.target)) // event.target is the form
    }).then((resp) => {
        return resp.json(); // or resp.text() or whatever the server sends
    }).then((body) => {
        // TODO handle body
    }).catch((error) => {
        // TODO handle error
    });
});

我所做的是把我已经写好的JS代码放在“Todo句柄体”中。

相关问题