I really don't know how to name this post. So I just simply listed all the technologies that involved.
The requirement goes like this: Displaying and modifying some JSON files on an embedded device using Vue.js and RESTful API.
Flask-RESTPlus
Flask-RESTPlus is a very helpful extension if you want to describe your API and expose its documentation properly with Flask. It's not too hard to use. But I want to not only generate the API documentation but also serve the Vue.js web pages. I did some research and got this:
from flask import Flask, render_template, make_response
from flask_restplus import Resource, Api
app = Flask(__name__)
api = Api(app,
version='1.0',
title= 'title'
description= 'desc'
doc='/apis')
@api.route('/app')
class AppIndex(Resource):
def get(self):
headers = {'Content-Type': 'text/html'}
return make_response(render_template('index.html'), 200, headers)
...
if __name__ == '__main__':
app.run(debug=True)
The get()
function in AppIndex
class does the trick.
Vue.js
I've never used Vue.js before. Vue actually doesn't have a HTTP client built in. They say they had, but got rid of it eventually to keep the core compact. I kind of agree with that idea. So now Axios is used to handle the HTTP methods. There are some tricks.
Multiple requests
// Other imports...
import axios from "axios";
export default {
data() {
return {
// ...
};
},
components: {
// ...
},
computed: {
// ...
},
methods: {
// ...
},
mounted() {
const requestOne = axios.get("http://127.0.0.1:5000/json_file");
const requestTwo = axios.get("http://127.0.0.1:5000/json_data");
axios
.all([requestOne, requestTwo])
.then(
axios.spread((...responses) => {
this.$store.dispatch(
"updateJsonFileAction",
responses[0].data
);
this.$store.dispatch(
"updateJsonDataAction",
responses[1].data
);
})
)
.catch(errors => {
alert(errors);
});
}
};
Cross Origin Resource Sharing
But actually the above API call will fail if we just leave the whole thing like that. It would report an "Network error". After some research I found that was because the Flask server only accepts the requests from the same port number (5000). To fix this, I had to install Flask-CORS, an extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible. It's easy to use:
# ...
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app)
# ...
Deployment
To make the Vue.js project getting built for Flask template, we can add/edit the following three entries:
vue.config.js
// ...
publicPath: '',
assetsDir: '../static',
baseUrl: '',
And another one is Output directory. If we open up a Vue UI, it's in Parameters dialog box in build task. We set this parameter to templates
.
Then after "build", we can directly copy the generated templates and static folders into Flask directory.