I am trying to make a website using Flask, where I pass in HTML canvas data to a database and then use that data in another route. When I retrieve the data from the database, it's in the form of a list, here's an example of that list with only one element :
[(1, 'circle', '{"pencil":[{"startx":346,"starty":105,"endx":346,"endy":105,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":344,"endy":104,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":341,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":338,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":333,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":330,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":338,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":338,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":109,"thick":2,"color":"#000000"}],"line":[],"rectangle":[],"circle":[],"eraser":[]}', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAu4AAAHCCAYAAACwm0waAAAAAXNSR0IArs4c6QAAIABJREFUeF7t3W2SI9lVBuDr/vD8gOgmAsLegNkGrB22Ke4KQjEiAAAECBAgQIEBAcbcHCBAgQIAAAQIECCQQ D/vr4ThKs0KewAAAABJRU5ErkJggg==', '10', '10', '100', '100')]
Following several previous answers given in this type of question, I tried the following approach, first I used json.dumps()
:
In Flask:
files = json.dumps(files)
return render_template("edit.html", files=files)
In edit.html
, I pass it into a function simply as:
<button id="show" onclick="loadImages(`{{ files }}`)">View</button>
Finally in edit.js
, I try to read it in an array as follows:
function loadImages(sources) {
var canvas = document.getElementById("paint");
var ctx = canvas.getContext("2d");
console.log(sources);
sources = JSON.parse(sources);
console.log(typeof(sources));
for(var i = 0; i < sources.length; i ) {
ctx.drawImage(sources[i][3], sources[i][4], sources[i][5], sources[i][6], sources[i][7]);
}
}
But this returns an error:
Uncaught SyntaxError: Unexpected token p in JSON at position 18
at JSON.parse (<anonymous>)
at loadImages (edit.js:16)
at HTMLButtonElement.onclick (edit:39)
The output of the console.log(sources)
in the loadImages
function is :
[[1, "circle", "{"pencil":[{"startx":346,"starty":105,"endx":346,"endy":105,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":344,"endy":104,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":341,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":338,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":333,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":330,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":326,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":326,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":322,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":319,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":317,"endy":103,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":315,"endy":104,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":314,"endy":104,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":312,"endy":104,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":311,"endy":105,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":310,"endy":106,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":308,"endy":106,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":307,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":306,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":304,"endy":109,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":302,"endy":110,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":301,"endy":111,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":107,"thick":2,"color":"#000000"},{"startx":346,"starty":105,"endx":336,"endy":109,"thick":2,"color":"#000000"}],"line":[],"rectangle":[],"circle":[],"eraser":[]}", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAu4AAAHCCAYAAACwm0waAAAAAXNSR0IArs4c6QAAIABJREFUeF7t3W2SI9lVBuDr/vD8gOgmAsLegNkGrB22ARuAgAimDT/G022ItCuH7LRUkkpS3vPxTITDMK5Snvu8N1VvZ6eyfjX8Q4AAAQIECBAgQIBAeIFfhZ/QgAQIECBAgAABAgQIDMXdJiBAgAABAgQIECCQQEBxTxCSEQkQIECAAAECBAgo7vYAAQIECBAgQIAAgQQCinuCkIxIgAABAgQIECBAQHG3BwgQIECAAAECBAgkEFDcE4RkRAIECBAgQIAAAQKKuz1AgAABAgQIECBAIIGA4p4gJCMSIECAAAECBAgQUNztAQIECBAgQIAAAQIJBBT3BCEZkQABAgQIECBAgIDibg8QIECAAAECBAgQSCCguCcIyYgECBAgQIAAAQIEFHd7gAABAgQIECBAgEACAcU9QUhGJECAAAECBAgQIKC42wMECBAgQIAAAQIEEggo7glCMiIBAgQIECBAgAABxd0eIECAAAECBAgQIJBAQHFPEJIRCRAgQIAAAQIECCju9gABAgQIECBAgACBBAKKe4KQjEiAAAECBAgQIEBAcbcHCBAgQIAAAQIECCQQUNwThGREAgQIECBAgAABAoq7PUCAAAECBAgQIEAggYDiniAkIxIgQIAAAQIECBBQ3O0BAgQIECBAgAABAgkEFPcEIRmRAAECBAgQIECAgOJuDxAgQIAAAQIECBBIIKC4JwjJiAQIECBAgAABAgQUd3uAAAECBAgQIECAQAIBxT1BSEYkQIAAAQIECBAgoLjbAwQIECBAgAABAgQSCCjuCUIyIgECBAgQIECAAAHF3R4gQIAAAQIECBAgkEBAcU8QkhEJECBAgAABAgQIKO72AAECBAgQIECAAIEEAop7gpCMSIAAAQIECBAgQEBxtwcIECBAgAABAgQIJBBQ3BOEZEQCBAgQIECAAAECirs9QIAAAQIECBAgQCCBgOKeICQjEiBAgAABAgQIEFDc7QECBAgQIECAAAECCQQU9wQhGZEAAQIECBAgQICA4m4PECBAgAABAgQIEEggoLgnCMmIBAgQIECAAAECBBR3e4AAAQIECBAgQIBAAgHFPUFIRiRAgAABAgQIECCguNsDBAgQIECAAAECBBIIKO4JQjIiAQIECBAgQIAAAcXdHiBAgAABAgQIECCQQEBxTxCSEQkQIECAAAECBAgo7vYAAQIECBAgQIAAgQQCinuCkIxIgAABAgQIECBAQHG3BwgQIECAAAECBAgkEFDcE4RkRAIECBAgQIAAAQKKuz1AgAABAgQIECBAIIGA4p4gJCMSIECAAAECBAgQUNztAQIECBAgQIAAAQIJBBT3BCEZkQABAgQIECBAgIDibg8QIECAAAECBAgQSCCguCcIyYgECBAgQIAAAQIEFHd7gAABAgQIECBAgEACAcU9QUhGJECAAAECBAgQIKC42wMECBAgQIAAAQIEEggo7glCMiIBAgQIECBAgAABxd0eIECAAAECBAgQIJBAQHFPEJIRCRAgQIAAAQIECCju9gABAgQIECBAgACBBAKKe4KQjEiAAAECBAgQIEBAcbcHCBAgQIAAAQIECCQQUNwThGREAgQIECBAgAABAoq7PUCAAAECBAgQIEAggYDiniAkIxIgQIAAAQIECBBQ3O0BAgQIECBAgAABAgkEFPcEIRmRAAECBAgQIECAgOJuDxAgQIAAAQIECBBIIKC4JwjJiAQIECBAgAABAgQUd3uAAAECBAgQIECAQAIBxT1BSEYkQIAAAQIECBAgoLjbAwQIECBAgAABAgQSCCjuCUIyIgECBAgQIECAAAHF3R4gQIAAAQIECBAgkEBAcU8QkhEJECBAgAABAgQIKO72AAECBAgQIECAAIEEAop7gpCMSIAAAQIECBAgQEBxtwcIECBAgAABAgQIJBBQ3BOEZEQCBAgQIECAAAECirs9QIAAAQIECBAgQCCBgOKeICQjEiBAgAABAgQIEFDc7QECBAgQIECAAAECCQQU9wQhGZEAAQIECBAgQICA4m4PECBAgAABAgQIEEggoLgnCMmIBAgQIECAAAECBBR3e4AAAQIECBAgQIBAAgHFPUFIRiRAgAABAgQIECCguNsDBAgQIECAAAECBBIIKO4JQjIiAQIECBAgQIAAAcXdHiBAgAABAgQIECCQQEBxTxCSEQkQIECAAAECBAgo7vYAAQIECBAgQIAAgQQCinuCkIxIgAABAgQIECBAQHG3BwgQ6CLwxzHGke95X8cYH7vgWicBAgQIPF/gyB9iz1 NIxAgQODPAj OMT4FwfjfMca7ILMYgwABAgQSCyjuicMzOgECJwVeK 1HlOifxxgfdpMtV/vfy4sAAQIECNwggg==", "10", "10", "100", "100"]]
I tried multiple approaches to get this done, but this was the closest I could reach to what I want, how do I proceed to correct this?
CodePudding user response:
I found few problems in this code - all with template:
template in flask escapes data (to make it safer) so using
{{ file }}
it creates HTML with[[1, "circle", "{\"pencil\":[
You can see it in browser if you use
Show Page Source
(Ctrl U
).It needs
{{ file|safe }}
to create correct HTML[[1, "circle", "{\"pencil\":[
it doesn't need ticks in
loadImages( ``...`` )
because
files
puts string with" "
soloadImage
has to be in' '
onclick='loadImages({{ files|safe }})'
browser treats text from
files
as normal code so it parses data at loading and it doesn't needJSON.parse()
to draw image you have to create
Image
and assign data to.src
var img = new Image(); img.src = sources[i][3]; ctx.drawImage(img, ...)
Minimal working code
EDIT:
You don't have to use json.dumps(data)
but {{ data|tojson }}
Eventually you can use {{ data|safe }}
but it will need to change some " "
into ' '
.
from flask import Flask, request, render_template_string
import json
app = Flask(__name__)
data = [(1, 'circle',
'{"pencil":[\
{"startx":346,"starty":105,"endx":346,"endy":105,"thick":2,"color":"#000000"},\
{"startx":346,"starty":105,"endx":344,"endy":104,"thick":2,"color":"#000000"},\
{"startx":346,"starty":105,"endx":341,"endy":103,"thick":2,"color":"#000000"},\
{"startx":346,"starty":105,"endx":338,"endy":103,"thick":2,"color":"#000000"},\
{"startx":346,"starty":105,"endx":336,"endy":103,"thick":2,"color":"#000000"},\
{"startx":346,"starty":105,"endx":333,"endy":103,"thick":2,"color":"#000000"},\
{"startx":346,"starty":105,"endx":330,"endy":103,"thick":2,"color":"#000000"},\
{"startx":346,"starty":105,"endx":338,"endy":107,"thick":2,"color":"#000000"},\
{"startx":346,"starty":105,"endx":338,"endy":107,"thick":2,"color":"#000000"},\
{"startx":346,"starty":105,"endx":336,"endy":107,"thick":2,"color":"#000000"},\
{"startx":346,"starty":105,"endx":336,"endy":109,"thick":2,"color":"#000000"}],\
"line":[],"rectangle":[],"circle":[],"eraser":[]\
}',
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAAAAACoWZBhAAAAMklEQVR4nEXNwQkAMBACwfFI/y2bxwXia8FFUwF1pCCNJTIIwaD04ctsKRyaldI/9i8u1iwOE6FA880AAAAASUVORK5CYII=',
'10', '10', '10', '10'
)]
@app.route('/', methods=['GET', 'POST'])
def index():
text = json.dumps(data)
return render_template_string('''
<script>
function loadImages(sources) {
console.log(sources);
var canvas = document.getElementById("paint");
var ctx = canvas.getContext("2d");
for(var i = 0; i < sources.length; i ) {
var data = sources[i]
console.log(data[3]);
var img = new Image();
img.src = data[3];
ctx.drawImage(img, data[4], data[5]); //, data[6], data[7]);
}
}
</script>
<body>
<h1>files</h1>
<pre>{{ files }}</pre>
<h1>files|safe</h1>
<pre>{{ files|safe }}</pre>
<h1>files|tojson</h1>
<pre>{{ files|tojson }}</pre>
<hr>
<canvas id="paint" width="100" height="100"></canvas><br/>
<button id="show" onclick='loadImages({{ files|safe <button id="show" onclick='loadImages({{ files|safe }})'>View files|safe</button>
<button id="show" onclick='loadImages({{ data|tojson }})'>View data|tojson</button>
<button id="show" onclick="loadImages({{ data|safe }})">View data|safe</button>
</body>
''', files=text, data=data)
if __name__ == '__main__':
#app.debug = True
app.run()
For your data:image
I get error image broken
so I use my small icon 10x10
but I don't know why but sometimes I have to click button two times to see image.