如何连接 Vue.js 作为前端和 Fastapi 作为后端

How to connect Vue.js as frontend and Fastapi as backend

我正在 Jobs Portal 上构建一个项目,我需要 Vue 作为前端和 Fastapi 作为后端(添加、删除更新)。我想知道我是否可以将它们连接起来。

I want to know if i can connect these both or not.

快速回答:是的,您可以连接。

但是有很多方法,您可以使用 Jinja 之类的东西呈现模板,或者您可以使用 Vue CLI 之类的东西创建一个完全不同的项目,您可能想使用 Nginx 或 Apache 等东西来连接两者。

让我们用 Jinja 创建一个示例应用程序

结构

├── main.py
└── templates
    └── home.html

后端- main.py

  • 我们在 / 中为我们的前端提供服务,并在该路径中呈现我们的 home.html
  • 我们正在使用模板文件夹来保存我们的 HTML 并将其传递给 Jinja。
  • 此外,我们将从我们的 front-end 向 /add 发送请求。
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel

templates = Jinja2Templates(directory="templates") 

app = FastAPI()


class TextArea(BaseModel):
    content: str


@app.post("/add")
async def post_textarea(data: TextArea):
    print(data.dict())
    return {**data.dict()}


@app.get("/")
async def serve_home(request: Request):
    return templates.TemplateResponse("home.html", {"request": request})

前端 - home.html

  • 让我们创建一个具有文本区域和按钮的虚拟应用程序。
  • 我们正在使用 Axios 将我们的请求发送到后端。
  • 由于它们 运行 在同一个端口上,我们可以将 /add 直接传递给 Axios。
<html>
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<body>
    <div id="app">
        <textarea name="" id="content" cols="30" rows="10" v-model="content"></textarea>
        <button @click="addText" id="add-textarea">click me</button>
    </div>

    <script>
        new Vue({
            el: "#app",
            data: {
                title: '',
                content: ''
            },
            methods: {
                addText() {
                    return axios.post("/add", {
                        content: this.content
                    }, {
                        headers: {
                            'Content-type': 'application/json',
                        }
                    }).then((response) => {
                        console.log("content: " + this.content);
                    });
                }
            }
        });
    </script>
</body>

</html>

最后,您将得到一个看起来很糟糕的文本区域和一个按钮。但它会帮助你更好地理解事物。

 {'content': 'Hello textarea!'}
INFO:     127.0.0.1:51682 - "POST /add HTTP/1.1" 200 OK

你可以做到,在我看来,这是一种非常干净的方式。 我能想到的最好办法是使用 Node.js/npm 将 Vue 应用程序捆绑到 dist/ 文件夹(默认情况下)

vue-cli-service build

然后我使用这样的项目文件夹结构

├── dist/ <- Vue-CLI output
    └── index.html
├── src/ <- Vue source files
└── app.py

要实现相同的项目设置,您只需使用 vue create 初始化一个 Vue 项目并在同一文件夹中创建您的 Python 项目(使用 IDE 如 Pycharm 例如,请确保您不会用另一个覆盖一个)。

然后你可以使用FastAPI.staticfiles.StaticFiles来为他们服务

# app.py

app.mount('/', StaticFiles(directory='dist', html=True))

记得将上面的 app.mount() 行放在所有其他路由之后,因为它会覆盖后面的每条路由。

你甚至可以使用vue-cli-service build --watch,这样Vue代码的每一个变化都会立即反映在HTML文件中,你只需要在浏览器上按F5就可以看到这些变化。

您也可以将 dist 文件夹输出更改为其他内容,使用 vue-cli-service build --dest=<folder name> 并更改上面 app.mount() 行中的 directory 参数。 (根据 Vue-CLI docs

这是我使用该设置的项目之一:https://github.com/KhanhhNe/sshmanager-v2