get data sent from flask to html - python

I am doing a flask application and I have a issue related to data sent from render_template() in flask to html web page.
This is my flask code ( I want to pass a number)
screenx = ((int(width[0][0]) - 0))
return render_template('/barchart.html', screen = screenx)
while this is my html code.
<canvas id="myCanvas" width="1024" height="768"></canvas>
<script >
screenx1={{screen}}
count = 0;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
myint = {{ mydict }}
console.log(" queste sono le coordinates", myint)
//var coordinates = canvas.toDataURL("text/plain");
//console.log(" queste sono le coordinates", coordinates)
var ref = canvas.toDataURL("image/png");
//console.log(ref)
//var imageObj = document.getElementById("mappa2");
//ctx.drawImage(imageObj,300,100);
var markerObj = new Image();
ref.onload = function() {
context.drawImage(ref, 0, 0, 1024,768);
};
markerObj.onload = function() {
context.drawImage(markerObj, 0,0, 20,20);
markerObj.style['z-index'] = "1";
};
markerObj.src = "https://cdn-icons-png.flaticon.com/512/684/684908.png";
var canvas = document.getElementById("myCanvas");
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var ctx = canvas.getContext("2d");
var canvasData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
</script>
</body>
I tried to get the data by using this
{{ screen}}
but nothing is sent.
Please can you help me ?

Flask
screenx = ((int(width[0][0]) - 0))
return render_template('/barchart.html', data=screenx)
HTML
screenx1={{data}}
Use data instead of screen?

Related

How to print leaflet map in pdf using django-wkhtmltopdf?

I have a django app I am trying to print a leaflet map in pdf using django-wkhtmltopdf, but the map is not rendering correctly. I even try to give more time to the 'javascript-delay' parameter but is giving me the same result.
Here is the image of the map:
from wkhtmltopdf.views import PDFTemplateResponse
class MyPDFView(View):
template='agrimensuras/project_pdf.html' # the template
def get(self, request, pk):
project = get_object_or_404(Project, id = int(pk))
data = {"project": project}
response = PDFTemplateResponse(request=request,
template=self.template,
filename="hello.pdf",
context= data,
show_content_in_browser=False,
cmd_options={'margin-top': 10,
"zoom":1,
"viewport-size" :"1366 x 513",
'javascript-delay':1000,
'footer-center' :'[page]/[topage]',
"no-stop-slow-scripts":True},
)
return response
In the template (I am just showing the relevant pieces of code):
<!--Importing leaflet-->
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.9.3/dist/leaflet.css"
integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI="
crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.9.3/dist/leaflet.js"
integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM="
crossorigin=""></script>
<!--Defining the div-->
<div id="map" ></div>
<!--Defining the map-->
<script type="text/javascript">
var map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
minZoom: 5,
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(map);
var marker = L.marker([51.5, -0.09]).addTo(map);
var circle = L.circle([51.508, -0.11], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 500
}).addTo(map);
var polygon = L.polygon([
[51.509, -0.08],
[51.503, -0.06],
[51.51, -0.047]
]).addTo(map);
</script>

Saving image captured from webcam

I'm building a Django project in which I need to take a picture from webcam, and then store it in my database and as a file. I'm saving the source in the database, but I'm having some trouble saving it as a file.
Here is my code:
html:
<form method="POST" action="{% url 'takePhoto' %}" enctype="multipart/form-data">
{% csrf_token %}
<video id="video" autoplay ></video>
<canvas id="canvas"></canvas>
<input type="hidden" name="photo" id="photo" value=""/>
<button id="startbutton1" class="btn btn-outline-secondary btn-sm">Take Photo</button>
<button id="submit" type="submit">submit</button>
<script src="{% static 'scripts/script.js' %}"></script>
javascript:
(function() {
var width = 320;
var height = 0;
var streaming = false;
var video = null;
var canvas = null;
var photo = null;
var startbutton1 = null;
function startup() {
video = document.getElementById('video');
canvas = document.getElementById('canvas');
photo = document.getElementById('photo');
startbutton1 = document.getElementById('startbutton1');
navigator.mediaDevices.getUserMedia({video: true, audio: false})
.then(function(stream) {
video.srcObject = stream;
video.play();
})
.catch(function(err) {
console.log("An error occurred: " + err);
});
video.addEventListener('canplay', function(ev){
if (!streaming) {
height = video.videoHeight / (video.videoWidth/width);
if (isNaN(height)) {
height = width / (4/3);
}
video.setAttribute('width', width);
video.setAttribute('height', height);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
streaming = true;
}
}, false);
startbutton1.addEventListener('click', function(ev){
takepicture();
ev.preventDefault();
}, false);
clearphoto();
}
function clearphoto() {
var context = canvas.getContext('2d');
context.fillStyle = "#AAA";
context.fillRect(0, 0, canvas.width, canvas.height);
var data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);
}
function takepicture() {
var context = canvas.getContext('2d');
if (width && height) {
canvas.width = width;
canvas.height = height;
context.drawImage(video, 0, 0, width, height);
var data = canvas.toDataURL('image/png');
photo.value=data;
} else {
clearphoto();
}
}
window.addEventListener('load', startup, false);
})();
views:
def takePhoto(request):
print("works")
if not request.session.get('logged_in'):
return redirect('/appChallenge/login')
if request.method== 'POST':
user = User.objects.get(username=request.session["username"])
img = request.POST.get("photo")
image = img
imagePath="/media"
a=str(img)
image = image.save(f"{imagePath}/{a}.png")
imgInfo= Image(user=user, img=img)
imgInfo.save()
print("works")
return render(request, 'page.html')
When I click submit, it says "'str' object has no attribute 'save'"
Please help. Thanks.
If your js/html code works, you will receive a raw image data encoded to base64 in your view 'takePhoto'. Try
print(img) to see something like "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAADwCAYAA...."
Maybe you will see just "iVBORw0KGgoAAAANSUhEUgAAAUAAAADwCAYAA...." without meta data.
So your 'img' is just a string with base64 encoded value, that hasn't method 'save'.
First, you need to get rid of "data:image/png;base64," in your raw image data, if your image string contains it. It is meta data and base64 could not decode it. You can do it at front end side:
var data = canvas.toDataURL('image/png').replace(/^data:image\/png;base64,/, "")
Or back end:
img = request.POST.get("photo").replace('data:image/png;base64,', '')
Next you need to use django ContentFile to create a file-like object. You need to simulate file with its method .read(). Also you need to decode base64 encoded image data:
import base64
from django.core.files.base import ContentFile
def takePhoto(request):
print("works")
if not request.session.get('logged_in'):
return redirect('/appChallenge/login')
if request.method== 'POST':
user = request.user
# remove meta data from base64 encoded data, you can also
# use 'split(',')[1]' to remove all before ','
img = request.POST.get("photo").replace('data:image/png;base64,', '')
# create a file-like object with your image data
image_file_like = ContentFile(base64.b64decode(img))
# first you need to create object
image = Image(user=user)
# and then save image into your model object
# note: only if your 'img' field is 'ImageField' or similar
image.img.save("filename.png", image_file_like)
image.save()
print("works")
return render(request, 'page.html')
P.S:
You don't need to add 'media' prefix in your image file name while saving it.
You should add MEDIA_ROOT variable in your settings.py like this:
BASE_DIR = Path(__file__).resolve().parent.parent # or manually set the path of your project
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
And all files automatically will be saved in your project media directory.

Generate dynamic div containers on submit in Flask app

I am new in Flask. My goal is to generate dynamic div containers every time I upload a dxf file and next submit happens. For example: one file uploaded- one div shown; two files uploaded- two divs shown and so on.
I can convert uploaded dxf files to .png images and I would like to show these images in div elements displayed after every upload.
I use input tag to upload files (type='file') and Java Script to generate dynamic elements (divs and their child tags).
The problem is that every time I upload file, the template is loading again and no new content is shown except the image of the last uploaded dxf. Please, give me a piece of advice to solve it.
HTML
...
<form enctype="multipart/form-data" id="uploadForm" action="/upload_files" name="uploadForm" method="post">
DXF file: <input type="file" id="dxfUpload" onchange="form.submit(); createConfigure();" name="dxfUpload" />
<div id="calcHolder" name="calcHolder">
<script type="text/javascript">
function createConfigure() {
var div = document.createElement("div");
div.id = "dxf-"+Math.random() * 100000000000000000 + "-"
+ window.performance.now() * 100000000000000000;
id_div=div.id;
div.className = 'border pad';
div.style.width = "640px";
div.style.height = "200px";
document.getElementById("calcHolder").appendChild(div);
var img = document.createElement("img");
img.setAttribute("src", "{{url_for('static', filename=dxfName+'.png')}}");
img.setAttribute("alt", "no image");
img.setAttribute("height", "120px");
img.setAttribute("width", "120px");
document.getElementById(id_div).appendChild(img);
var array = ["Carbon Steel","Stainless Steel","Aluminium"];
var selectMaterial = document.createElement("select");
document.getElementById(id_div).appendChild(selectMaterial);
for (var i = 0; i < array.length; i++) {
var option = document.createElement("option");
option.value = array[i];
option.text = array[i];
selectMaterial.appendChild(option);
}
var selectThickness = document.createElement("select");
document.getElementById(id_div).appendChild(selectThickness);
for (i = 1; i <= 16; i++) {
var opt = document.createElement('option');
//opt.value = i;
opt.innerHTML = i + ' mm';
selectThickness.appendChild(opt);
}
var quantity = document.createElement("input")
quantity.type="number";
quantity.value="1";
quantity.name="quantity";
quantity.min="1";
quantity.max="50";
quantity.onkeyup= function maxReach(){if(quantity.value > 50) quantity.value=50;};
document.getElementById(id_div).appendChild(quantity);
var btn = document.createElement("button");
btn.innerHTML = "Delete";
btn.type = "button";
document.getElementById(id_div).appendChild(btn);
btn.onclick = function() {div.remove();};
}
</script>
{{ html | safe }}
</div>
</form>
...
Python
#app.route('/upload_files', methods=['POST'])
def upload_files():
try:
if request.method == 'POST':
dxf_file = request.files['dxfUpload']
full_filename = os.path.join(app.config['UPLOAD_FOLDER'],dxf_file.filename)
dxf_file.save(full_filename)
first = DXF2IMG()
first.convert_dxf2img([full_filename],img_format='.png')
html="<img src="+url_for('static', filename=dxf_file.filename+'.png' )+" width='120' height='120' />"
return render_template('upload_files.html',dxfName=dxf_file.filename, html=html)
except:
...
#something happens
The result now
Desired result
Once the form.submit() function is executed, the form will be sent as a regular post request. For this reason, the following function is no longer executed and the entire page is reloaded.
In order to submit the form and change the content of the existing page, it is necessary to use AJAX.
This example shows you how to submit the form to the server and receive a JSON response containing the URLs of the received file and the generated image.
As soon as the submit button is pressed, the form data is packed into a FormData object and sent via AJAX using the fetch function. The browser's default behavior for a submit event is suppressed and the form is reset. The received file is processed by the server and the associated URLs are sent back to the client in JSON format. Now the document can be changed with the received data.
Remember this is just a minimal example to help you achieve your goals and implement your concept.
Flask (app.py)
import os
import ezdxf
from ezdxf.addons.drawing import matplotlib
from flask import Flask
from flask import (
jsonify,
make_response,
render_template,
url_for
)
from werkzeug.utils import secure_filename
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
def dxf2png(source, target):
doc = ezdxf.readfile(source)
msp = doc.modelspace()
auditor = doc.audit()
if auditor.has_errors:
raise Exception('Conversion failed.')
matplotlib.qsave(doc.modelspace(), target)
#app.route('/upload', methods=['POST'])
def upload():
if 'dxf-file' in request.files:
file = request.files['dxf-file']
if file.filename != '':
filename = secure_filename(file.filename)
filepath = os.path.join(app.static_folder, filename)
destname, _ = os.path.splitext(filename)
destname = f'{destname}.png'
destpath = os.path.join(app.static_folder, destname)
file.save(filepath)
try:
dxf2png(filepath, destpath)
except:
os.remove(filepath)
return make_response('', 400)
return make_response(
jsonify(
target=url_for('static', filename=filename),
preview=url_for('static', filename=destname)
),
200
)
return make_response('', 400)
HTML (templates/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Index</title>
<style media="screen">
.preview {
width: 120px;
height: auto;
}
</style>
</head>
<body>
<form name="dxf-upload" method="post" enctype="multipart/form-data">
<input type="file" name="dxf-file" />
<input type="submit" />
</form>
<div id="dxf-files"></div>
<script type="text/javascript">
((uri) => {
function createPreview(target, preview) {
const divElem = document.createElement('div');
divElem.innerHTML = `<img src="${preview}" class="preview" />`;
const outElem = document.getElementById('dxf-files');
outElem.append(divElem);
}
const form = document.querySelector('form[name="dxf-upload"]');
form.addEventListener('submit', evt => {
evt.preventDefault();
const formData = new FormData(evt.target);
fetch(uri, {
method: 'POST',
body: formData
}).then(resp => resp.json())
.then(data => {
const { target, preview } = data;
createPreview(target, preview);
});
evt.target.reset();
});
})({{ url_for('.upload') | tojson }});
</script>
</body>
</html>

How to capture images using OpenCV and Flask?

I'm trying to run this website that takes using flask that takes a picture when u press next but it only works on the first time I go to that URL. When I get redirected to the same url then it no longer works.
Please help I've been stuck on this for months now and don't know what to do anymore.
from camera import VideoCamera
import cv2
import time
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hello'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///drug1.sqlite'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
med_list = []
timestr = time.strftime("%Y%m%d-%H%M%S")
cam = cv2.VideoCapture(0)
video_stream = VideoCamera()
#app.route('/')
def index():
return render_template('vid.html')
def gen(camera):
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
#app.route('/video_feed')
def video_feed():
#app.route("/scan", methods =["POST","GET"])
def scan():
drug_list = []
if request.method == 'POST':
bc = request.form['barcode']
print(bc)
if request.form['submit_button'] == 'Next':
return redirect(url_for('scan2',image=image_link,drug=drug,strength=strength,med_list=med_list))
return render_template("scan.html")
#app.route("/scan2", methods =["POST","GET"])
def scan2():
drug = session.get("drug",None)
image_link = session.get("image_link",None)
strength = session.get("strength",None)
if request.method == 'POST':
if request.form['submit_button'] == 'Next':
retval, frame = cam.read()
cv2.imwrite('img{}.png'.format(timestr), frame)
return redirect(url_for('scan'))
return render_template("scan2.html",image=image_link,drug=drug,strength=strength)
If you want to take a picture using built-in camera in user's laptop then you have to use JavaScript because only web browser has access to user's camera - server can't access user's computer.
Here is example which displays stream from user's camera and it can take screenshot. But it still need JavaScript to send it to server.
from flask import Flask, render_template_string
app = Flask(__name__)
#app.route('/')
def index():
return render_template_string('''
<video id="video" width="640" height="480" autoplay style="background-color: grey"></video>
<button id="snap">Take Photo</button>
<canvas id="canvas" width="640" height="480" style="background-color: grey"></canvas>
<script>
// Elements for taking the snapshot
var video = document.getElementById('video');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// Get access to the camera!
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// Not adding `{ audio: true }` since we only want video now
navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
//video.src = window.URL.createObjectURL(stream);
video.srcObject = stream; // assing stream to <video>
video.play(); // play stream
});
}
// Trigger photo take
document.getElementById("snap").addEventListener("click", function() {
context.drawImage(video, 0, 0, 640, 480); // copy video frame to canvas
});
</script>
''')
if __name__ == '__main__':
app.run(debug=True)
EDIT:
Here is example which can send image on server.
And few useful links which I had with this code
https://developers.google.com/web/fundamentals/media/capturing-images
https://github.com/jhuckaby/webcamjs
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
from flask import Flask, render_template_string, request
app = Flask(__name__)
#app.route('/')
def index():
return render_template_string('''
<video id="video" width="640" height="480" autoplay style="background-color: grey"></video>
<button id="send">Take & Send Photo</button>
<canvas id="canvas" width="640" height="480" style="background-color: grey"></canvas>
<script>
// Elements for taking the snapshot
var video = document.getElementById('video');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// Get access to the camera!
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// Not adding `{ audio: true }` since we only want video now
navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
//video.src = window.URL.createObjectURL(stream);
video.srcObject = stream;
video.play();
});
}
// Trigger photo take
document.getElementById("send").addEventListener("click", function() {
context.drawImage(video, 0, 0, 640, 480); // copy frame from <video>
canvas.toBlob(upload, "image/jpeg"); // convert to file and execute function `upload`
});
function upload(file) {
// create form and append file
var formdata = new FormData();
formdata.append("snap", file);
// create AJAX requests POST with file
var xhr = new XMLHttpRequest();
xhr.open("POST", "{{ url_for('upload') }}", true);
xhr.onload = function() {
if(this.status = 200) {
console.log(this.response);
} else {
console.error(xhr);
}
alert(this.response);
};
xhr.send(formdata);
}
</script>
''')
#app.route('/upload', methods=['GET', 'POST'])
def upload():
if request.method == 'POST':
#fs = request.files['snap'] # it raise error when there is no `snap` in form
fs = request.files.get('snap')
if fs:
print('FileStorage:', fs)
print('filename:', fs.filename)
fs.save('image.jpg')
return 'Got Snap!'
else:
return 'You forgot Snap!'
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True, port=5000)
EDIT:
I found example which sends stream to server, it draws red border and text with current time and it sends it back to browser.
# https://developers.google.com/web/fundamentals/media/capturing-images
# https://github.com/jhuckaby/webcamjs
# https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
# https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
# https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
from flask import Flask, render_template_string, request, make_response
import cv2
import numpy as np
import datetime
app = Flask(__name__)
#app.route('/')
def index():
return render_template_string('''
<video id="video" width="320" height="240" autoplay style="background-color: grey"></video>
<button id="send">Take & Send Photo</button>
<canvas id="canvas" width="320" height="240" style="background-color: grey"></canvas>
<img id="image" src="" width="320" height="240" style="background-color: grey"></img>
<img id="image64" src="" width="320" height="240" style="background-color: grey"></img>
<script>
// Elements for taking the snapshot
var video = document.getElementById('video');
// Element to display snapshot
// you need canvas to get image. canvas can be hidden using `createElement("canvas")`
// var canvas = document.createElement("canvas");
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var image = document.getElementById('image');
var image64 = document.getElementById('image64');
// Get access to the camera!
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// Not adding `{ audio: true }` since we only want video now
navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
//video.src = window.URL.createObjectURL(stream);
video.srcObject = stream;
video.play();
//console.log('setInterval')
window.setInterval(function() {
//context.drawImage(video, 0, 0);
context.drawImage(video, 0, 0, 320, 240); // better use size because camera may gives data in different size then <video> is displaying
image64.src = canvas.toDataURL();
canvas.toBlob(upload, "image/jpeg");
}, 100);
});
}
// Trigger photo take
document.getElementById("send").addEventListener("click", function() {
//context.drawImage(video, 0, 0);
context.drawImage(video, 0, 0, 320, 240); // better use size because camera may gives data in different size then <video> is displaying
image64.src = canvas.toDataURL();
canvas.toBlob(upload, "image/jpeg");
});
function upload(file) {
// create form
var formdata = new FormData();
// add file to form
formdata.append("snap", file);
// create AJAX connection
var xhr = new XMLHttpRequest();
xhr.open("POST", "{{ url_for('upload') }}", true);
xhr.responseType = 'blob';
// define function which get response
xhr.onload = function() {
if(this.status = 200) {
//console.log(this.response);
} else {
console.error(xhr);
}
//alert(this.response);
//img.onload = function(){
// ctx.drawImage(img, 0, 0)
//}
image.src = URL.createObjectURL(this.response); // blob
};
// send form in AJAX
xhr.send(formdata);
//image.src = URL.createObjectURL(file);
}
</script>
''')
def send_file_data(data, mimetype='image/jpeg', filename='output.jpg'):
# https://stackoverflow.com/questions/11017466/flask-to-return-image-stored-in-database/11017839
response = make_response(data)
response.headers.set('Content-Type', mimetype)
response.headers.set('Content-Disposition', 'attachment', filename=filename)
return response
#app.route('/upload', methods=['GET', 'POST'])
def upload():
if request.method == 'POST':
#fs = request.files['snap'] # it raise error when there is no `snap` in form
fs = request.files.get('snap')
if fs:
#print('FileStorage:', fs)
#print('filename:', fs.filename)
# https://stackoverflow.com/questions/27517688/can-an-uploaded-image-be-loaded-directly-by-cv2
# https://stackoverflow.com/a/11017839/1832058
img = cv2.imdecode(np.frombuffer(fs.read(), np.uint8), cv2.IMREAD_UNCHANGED)
#print('Shape:', img.shape)
# rectangle(image, start_point, end_point, color, thickness)
img = cv2.rectangle(img, (20, 20), (300, 220), (0, 0, 255), 2)
text = datetime.datetime.now().strftime('%Y.%m.%d %H.%M.%S.%f')
img = cv2.putText(img, text, (5, 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)
#cv2.imshow('image', img)
#cv2.waitKey(1)
# https://jdhao.github.io/2019/07/06/python_opencv_pil_image_to_bytes/
ret, buf = cv2.imencode('.jpg', img)
#return f'Got Snap! {img.shape}'
return send_file_data(buf.tobytes())
else:
return 'You forgot Snap!'
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True, port=5000)
Camera works with HTTP only on address 127.0.0.1
On 0.0.0.0 it needs HTTPS but it needs cert. For test you can use ssl_context='adhoc' but browser will warn you that it is insecure connection and you will have to accept it.
app.run(host='0.0.0.0', port=5000, ssl_context='adhoc')

Update Api from Ajax to Python

I don't know how to append data to API in Flask from JS to Python without using a global list in Python route, which is causing all users to see same API info.
I have an ajax post request in my JS static file that allows a user to select an item and upon selecting that item it posts that data to Python route which then loads data and appends it to a global array. And then within the route I return the JSON list to the api. I am trying to figure out another way to do this because with this method first of all from my understanding global variables are God awful for this exact reason because all users can see the global api info.
// On load cart
window.onload = function wowzers(){
var array = [];
var sum = 0;
// Get Data
var xhr = new XMLHttpRequest();
xhr.open('GET', 'pricing/orders/' + username +'/api', true);
xhr.onload = function(){
var data = JSON.parse(this.response);
if(xhr.status >= 200 && xhr.status < 400){
for(x in data){
for(key in data[x]){
array.push(Number(data[x][key]));
sum+=Number(data[x][key]);
subtotal.innerHTML = sum;
row = cart.insertRow(-1);
// Delete Data
row.addEventListener('click', function deleterow(){
index = this.rowIndex;
$.post('pricing/orders/delete', {
delete_item: index
});
cart.deleteRow(index);
subtotal.innerHTML = sum-Number(cart.rows[index].cells[1].innerHTML);
});
cell1 = row.insertCell(0);
cell2 = row.insertCell(1);
cell3 = row.insertCell(2);
cell1.innerHTML = key;
cell2. innerHTML = data[x][key];
cell3. innerHTML = "<button class='btn btn-danger'>Delete</button>"
}
}
console.log(sum);
}else{
console.log(error)
}
}
xhr.send()
}
//Dynamic Cart
for(x = 0; x < tablerows; x++){
table.rows[x].addEventListener('click', addCartItem);
}
function addCartItem(ev){
var array = [];
var sum = 0;
index = this.rowIndex;
equipmentCell = table.rows[index].cells[0];
priceCell = table.rows[index].cells[1];
equipmentName = equipmentCell.innerHTML;
equipmentPrice = priceCell.innerHTML;
// Post Data
$.post('/pricing/orders/' + username + '/api', {
javascript_data: JSON.stringify({[equipmentName]:equipmentPrice})
});
cartrow = cart.insertRow(-1);
// Delete Data
cartrow.addEventListener('click', function deleterow(){
index = this.rowIndex;
subtotal.innerHTML = sum-Number(cart.rows[index].cells[1].innerHTML);
$.post('pricing/orders/delete', {
delete_item: index
});
cart.deleteRow(index);
});
cell1 = cartrow.insertCell(0);
cell2 = cartrow.insertCell(1);
cell3 = cartrow.insertCell(2);
cell1.innerHTML= equipmentName;
cell2.innerHTML = equipmentPrice;
cell3.innerHTML = "<button class='btn btn-danger'>Delete</button>";
// Open Api information
var xhr = new XMLHttpRequest();
xhr.open('GET', 'pricing/orders/' + username +'/api', true);
xhr.onload = function(){
var data = JSON.parse(this.response);
if(xhr.status >= 200 && xhr.status < 400){
for(x in data){
for(y in data[x]){
array.push(Number(data[x][y]));
sum+=Number(data[x][y]);
subtotal.innerHTML = sum;
}
}
}else{
console.log(error);
}
}
xhr.send();
}
Route Logic
# ---------------------------------- USER CART API -----------------------------
#app.route('/pricing/orders/<user_name>/api', methods=['POST', 'GET'])
#login_required
def api(user_name):
user_name = current_user.username
if request.method == 'POST':
cart.append(json.loads(request.form["javascript_data"]))
return jsonify(cart)
# ---------------------------- DELETE ITEM IN CART ROUTE ----------------------------------
#app.route('/pricing/orders/delete', methods=['POST', 'GET'])
#login_required
def delete_item():
if request.method == 'POST':
print(cart[json.loads(request.form["delete_item"])])
cart.pop(json.loads(request.form["delete_item"]))
print(cart)
return jsonify({"whoa": "there"})
# ----------------------------- DISPLAY CART BADGE LENGTH---------------------------------
#app.context_processor
def inject_badge_length():
badge_length = len(cart)
return {'BADGE_LENGTH' : badge_length}
I'm hoping I can post data to Python route and then append particular data to API without global list so all users are only able to view their own data. I'm a beginner in the RESTFUL API arena, and just need pointing in the right direction.
It seems like you are running into an issue with storing data.
Most likely, you will want some type of ORM like SQLAlchemy to handle your data storage. It has a bit of a learning curve, but will make things much easier to manage in the long run.

Categories

Resources