I am building a very basic CARTO application using Vue JS and Flask. The full code can be found in this github repository.
The application works like this:
The user select an option in a modal form and clicks on visualize button. This sends a Vue method called loadMap which sends a POST request with a query string (query computed property) value as a payload.
Then, it redirects the route to another template (map.html) and takes a variable (features) that is generated from a SQL API call.
This variable is a GeoJSON which will populate the data source of the map.
The problem is that after doing the redirection, the map template does not render. This is my Python code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
from flask import Flask, render_template, request, url_for, redirect
app = Flask(__name__, static_folder='static', template_folder='templates')
@app.route('/')
def home():
"""Displays the homepage."""
return render_template('index.html')
@app.route('/query', methods=['POST'])
def query():
data = request.get_json()
query = data['query']
return redirect(url_for('map', query=query))
@app.route('/map', methods=['GET'])
def map():
query = request.args['query']
url = 'https://ramiroaznar.carto.com/api/v2/sql?q={}&format=geojson'.format(query)
session = requests.Session()
r = session.get(url)
features = r.json()
return render_template('map.html', features=features)
if __name__ == '__main__':
app.run(debug=True)
It looks like the POST and GET call are done correctly, but then the redirection is not launched, so the map is not loaded:

How can I fix this problem? Is there a more elegant way to achieve this (loading a new website with data from an API call)?
The problem was located in my js code. So I fix it moving the map logic to the vue instance. I did also simplify the python code, in order to avoid using two templates. Now the app works, but I should refactor the js code to improve the performance (it takes too long to load) and scalalibility (the map logic should be moved again outside the vue instance). You can find the working example in this glitch repository.
The following snippet is my Flask python code...
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
from flask import Flask, render_template, request, url_for, redirect
app = Flask(__name__, static_folder='static', template_folder='templates')
@app.route('/')
def home():
"""Displays the homepage."""
return render_template('index.html')
@app.route('/data', methods=['GET'])
def data():
query = request.args.get('query')
url = 'https://ramiroaznar.carto.com/api/v2/sql?q={}&format=geojson'.format(query)
session = requests.Session()
r = session.get(url)
features = r.json()
return features
if __name__ == '__main__':
app.run(debug=True)
... and this is my js code:
Vue.config.ignoredElements = [/as-\w+/];
const vm = new Vue({
el: "#app",
data: {
geometryType: 'cities',
map: false,
features: {}
},
computed: {
query: function() {
let table = ''
if (this.geometryType == 'cities'){
table = 'ne_10m_populated_places_simple';
} else {
table = 'world_borders';
}
return `select * from ${table}`
}
},
methods: {
loadMap: function() {
this.map = true;
this.$http.get('/data', {params: {query: this.query}} ).then(response => {
this.features = JSON.parse(response.bodyText);
console.log(this.features);
}, response => {
console.log('an error ocurred')
})
}
},
watch: {
features: function() {
const map = new mapboxgl.Map({
container: 'map',
style: carto.basemaps.voyager,
center: [10.151367,51.172455],
zoom: 2,
scrollZoom: false
});
const nav = new mapboxgl.NavigationControl({ showCompass: false });
map.addControl(nav, 'top-left');
carto.setDefaultAuth({
username: 'cartovl',
apiKey: 'default_public'
});
console.log(this.features);
const source = new carto.source.GeoJSON(this.features);
const viz = new carto.Viz();
const layer = new carto.Layer('layer', source, viz);
layer.addTo(map, 'watername_ocean');
}
}
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With