Reputation: 1323
I'm building a project On Jobs Portal and I need Vue as frontend and FastAPI as backend for add, delete, update. I want to know if I can connect these both or not.
Upvotes: 9
Views: 20662
Reputation: 8659
Here are two solutions for using Vue for the entire frontend you can go modify the vue.config.js
file:
const { defineConfig } = require('@vue/cli-service')
const path = require('path');
module.exports = defineConfig({
transpileDependencies: true, //Transpile your dependencies
publicPath: "/static", //Path of static directory
outputDir: path.resolve(__dirname, '../static'), // Output path for the static files
runtimeCompiler: true,
devServer: {
// Write files to disk in dev mode, so FastAPI can serve the assets
port: 8080,
devMiddleware: {
writeToDisk: true,
}
},
})
Then in the vue-cli you can run either build or serve (this is in the task page) or in the console run
npm run build
This will transpile your staticfiles to the output folder you set on in the vue.config.js
file. Next are two options with and without jinja2
Without Jinja
Next go to main.py
on Fastapi and add the two lines below
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles #<-- Add this
app = FastAPI()
#static files & load
app.mount("/", StaticFiles(directory="static", html = True), name="static") #<-- Add this
There should be a index.html
page in the static folder the line with the app.mount("/", StaticFiles(directory="static", html = True), name="static")
sets the directory for the path to the static file and loads the html file to "/".
You can add, delete, update, and query using a GraphQL library
With jinja2
Go to main.py
on Fastapi and add the two lines below
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
app = FastAPI()
#static files & load
app.mount("/static", StaticFiles(directory="static", html = True), name="static")
templates = Jinja2Templates(directory="static")
@app.get("/")
async def serve_home(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
Here the index.html
page that is transpiled is loaded in as a jinja template. You can write your GET and POST functions on the main.js
Upvotes: 2
Reputation: 542
You can do it, in quite a clean way IMO.
The best I can come up with is using Node.js/npm to bundle the Vue app to a dist/
folder (by default)
vue-cli-service build
I then use the project folder structure like this
├── dist/ <- Vue-CLI output
└── index.html
├── src/ <- Vue source files
└── app.py
To archieve the same project setup, you can just simply init a Vue project using vue create
and create your Python project in a same folder (using a IDE like Pycharm for example, make sure you don't override one with the other).
Then you can use FastAPI.staticfiles.StaticFiles
to serve them
# app.py
app.mount('/', StaticFiles(directory='dist', html=True))
Remember to put the above app.mount()
line after all other routes though, since it will override every route that comes after.
You can even use vue-cli-service build --watch
so that every change in Vue code will be reflected in the HTML file right after, and all you need to do is to press F5 on your browser to see those changes.
You can change the dist
folder output to something else too, using vue-cli-service build --dest=<folder name>
and change directory
parameter in app.mount()
line above. (according to Vue-CLI docs)
Here is one of my projects using that setup: https://github.com/KhanhhNe/sshmanager-v2
Upvotes: 6
Reputation: 20618
I want to know if i can connect these both or not.
But there are many ways, you can render templates with something like Jinja or you can create a completely different project with something like Vue CLI and you might want to use something like Nginx or Apache etc to connect both.
So let's create an example app with Jinja
├── main.py
└── templates
└── home.html
main.py
/
and rendering our home.html
in that path./add
from our front-end.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
/add
to Axios directly.<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>
In the end, you will have a terrible looking textarea and a button. But it will help you to understand things better.
{'content': 'Hello textarea!'}
INFO: 127.0.0.1:51682 - "POST /add HTTP/1.1" 200 OK
Upvotes: 22