How to pickup file contents from HTML file input and hand off to API - python-asyncio

I can successfully send image data to an API endpoint with pyscript (1). I can also set up a form and pickup the binary data from a file. I want to put these together so that I pick up the image data and send it to the API in one call. They both use asyncio.ensure_future but I'm not sure how to combine these two processes (getting file data and posting file data to an API). Is there a way to combine these two processes with a single call to asyncio.ensure_future?
(1) send image data to API endpoint
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>GET, POST, PUT, DELETE example</title>
<link rel="icon" type="image/png" href="favicon.png" />
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
<py-config>
[[fetch]]
files = ["/request.py"]
</py-config>
</head>
<body><p>
Hello world request example! <br>
Here is the output of your request:
</p>
<py-script>
import asyncio
import json
from request import request # import our request function.
async def main():
baseurl = "https://jsonplaceholder.typicode.com"
# CLD
file = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII="
body = json.dumps({"upload_preset":"<preset>","file":file})
cldheaders={"Content-type": "application/json"}
cldurl = "https://api.cloudinary.com/v1_1/<cloudname>/upload"
new_post = await request(cldurl, body=body, method="POST", headers=cldheaders)
print(f"CLD request=> status:{new_post.status}, json:{await new_post.json()}")
asyncio.ensure_future(main())
</py-script>
<div>
<p>
You can also use other methods. See fetch documentation: <br>
https://developer.mozilla.org/en-US/docs/Web/API/fetch#parameters
</p>
</div>
<div>
<p>
See pyodide documentation for what to do with a FetchResponse object: <br>
https://pyodide.org/en/stable/usage/api/python-api.html#pyodide.http.FetchResponse
</p>
</div>
</body>
</html>
(2) process file from a form file input
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
<title>File Example</title>
<py-config>
[[fetch]]
files = ["/request.py"]
</py-config>
</head>
<body>
<p>This example shows how to read a file from the local file system and display its contents</p>
<br />
<p>Warning: Not every file type will display. PyScript removes content with tags such as XML, HTML, PHP, etc. Normal
text files will work.</p>
<br />
<p>No content type checking is performed to detect images, executables, etc.</p>
<br />
<label for="myfile">Select a file:</label>
<input type="file" id="myfile" name="myfile">
<br />
<br />
<div id="print_output"></div>
<br />
<p>File Content:</p>
<div style="border:2px inset #AAA;cursor:text;height:120px;overflow:auto;width:600px; resize:both">
<div id="content">
</div>
</div>
<py-script output="print_output">
import asyncio
from request import request # import our request function.
import json
from js import document, FileReader, console
from pyodide import create_proxy
from pyodide.http import pyfetch, FetchResponse
from typing import Optional, Any
async def process_file(event):
#print(event.target.files[0].name)
fileList = event.target.files.to_py()
for f in fileList:
#console.log(json.dumps(json.loads(f),indent=2))
#console.log(type(f))
data = await f.text()
console.log("name",f.name)
document.getElementById("content").innerHTML = data
async def main():
# Create a Python proxy for the callback function
# process_file() is your function to process events from FileReader
file_event = create_proxy(process_file)
# Set the listener to the callback
e = document.getElementById("myfile")
#console.log("value of e",e.name)
e.addEventListener("change", file_event, False)
asyncio.ensure_future(main())
</py-script>
</body>
sharing two scripts that show what I've done

Related

I can't show an html page

I have to develop a project for college using Spring. I started watching some tutorials and I can't show an html page. I do the same but it returns only one string.
I'm using visual studio code.
Controller:
package com.example.springteste.controllers;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class ProductController {
#GetMapping("/formulario")
public String formulario()
{
return "form";
}
}
My view is just inside templates
View:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<main>
<section id="sectionProduct">
<div>
<div id="sectionProduct-title">
<h1>
Título
</h1>
</div>
<div id="sectionProduct-form">
<form action="">
<div class="sectionProduct-form-inputLabel">
<input type="text" id="title" name="title">
<label for="title">
Título
</label>
</div>
</form>
</div>
</div>
</section>
</main>
</body>
</html>
I believe something is missing. I am a beginner in java and spring
If you want to return a view name from the controller method handler - you have to use #Controller annotation. Also make sure you put your views into the correct directory, according to your view resolver configuration.
About #RestController - as the name suggests, it shall be used in case of REST style controllers i.e. handler methods shall return the JSON/XML response directly to the client rather using view resolvers.
In your case the handler method will return "form" to the client.

AJAX + Flask update server request when filling form

On the Flask website there's a tutorial on how to use AJAX and this an example to display the sums of two numbers.
This is the python app
from flask import Flask, render_template, request, jsonify
# Initialize the Flask application
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/_add_numbers')
def add_numbers():
a = request.args.get('a', 0, type=int)
b = request.args.get('b', 0, type=int)
return jsonify(result=a + b)
if __name__ == '__main__':
app.run(
host="0.0.0.0",
port=int("80"),
debug=True
)
This is the HTML file
<!DOCTYPE html>
<html lang="en">
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"
rel="stylesheet">
<script type=text/javascript>
$(function() {
$('a#calculate').bind('click', function() {
$.getJSON('/_add_numbers', {
a: $('input[name="a"]').val(),
b: $('input[name="b"]').val()
}, function(data) {
$("#result").text(data.result);
});
return false;
});
});
</script>
</head>
<body>
<div class="container">
<div class="header">
<h3 class="text-muted">How To Manage JSON Requests</h3>
</div>
<hr/>
<div>
<p>
<input type="text" size="5" name="a"> +
<input type="text" size="5" name="b"> =
<span id="result">?</span>
<p>calculate server side
</form>
</div>
</div>
</body>
</html>
I see that with this example one is able to send a request to the server every time one clicks on the link, however, I would like to know if it's possible to skip this step and get the request overtime the text inputted by the user changes.
Yes. It's wasteful of resources, but you could change
$('a#calculate').bind('click', function() { to
$('input[name="a"]').change(function() {
And do the same for input b
Edit:
And, to test AS YOU TYPE:
$('input[name="a"]').on('input',function(e){
or:
$('input[name="a"]').keyup(function(e){

Grails formRemote tag error

I have been using grails for several weeks now, and have run into this problem when using the g:formRemote tag.
org.grails.taglib.GrailsTagException: [views/inventoryDetails/details.gsp:21] [views/inventoryDetails/details.gsp:21] Tag [formRemote] does not exist. No tag library found for namespace: g
for reference here is the .gsp page
<html>
<head>
<meta name="layout" content="bccmain" />
<title>Details - BCC Virtual Map and Inventory Tracker</title>
<g:javascript library="jquery" />
<link rel="stylesheet" href="${resource(dir: 'css', file: 'details.css')}" type="text/css">
<script>
$(document).ready(function () {
$("#database").addClass("active");
});
</script>
</head>
<body>
<div id ="content">
<g:formRemote name = "detailsUpdateForm" url = "[controller: 'InventoryDetails',action: 'ajaxUpdate']" update="updateBox">
<g:each in ="${details}" var = "d" status = "i">
<g:textField name="details" value = "${d.details}" class = "detailsblock"/>
<g:hiddenField name ="id" value = "${d.id}" />
<g:submitButton name = "submit" value = "Save" />
</g:each>
</g:formRemote>
<div id = "updateBox"></div>
</div>
</body>
</html>
I can't for the life of me figure out why the g:formRemote tag causes a problem, but other tags (run on different pages -- this one won't render) such as g:each will run without a problem. Thanks.
Most likely you are working on a Grails version that does not support "g:formRemote" any more. The formRemote tag and other Ajax related tags have been deprecated. You might want to think about a different approach.

jQuery mobile "pageinit" calls hashtag for short time

I'm currently building a page with jQuery mobile.
I need to load some custon JavaScript on one page, so I found the pageInit function.
Here's a short example of what i'm using:
page1.html:
<!doctype html>
<meta charset="uft-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>page1 | test page for jquery mobile</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.css">
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.js"></script>
<script src="js.js"></script>
<div data-role="page" id="page1">
<div data-role="header">
<h1>Page 1 Title</h1>
</div>
<div data-role="content">
go to page2
<p>Page 1 content goes here.</p>
</div>
<div data-role="footer">
<h4>Page 1 Footer</h4>
</div>
</div>
page2.html:
<!doctype html>
<meta charset="uft-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>page1 | test page for jquery mobile</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.css">
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.js"></script>
<script src="js.js"></script>
<div data-role="page" id="page2">
<div data-role="header">
<h1>Page 2 Title</h1>
</div>
<div data-role="content">
go to page1
<p id="addstuff">Page 2 content goes here.</p>
</div>
<div data-role="footer">
<h4>Page 2 Footer</h4>
</div>
</div>
js.js
$(document).delegate('#page2', 'pageinit', function() {
$('<div />', {
html: 'Some text that was added via jQuery'
}).appendTo('#addstuff');
});
So I need to execute some JavaScript on page2.html. It actually works great (the div was created and you see the text). But when I'm clicking on a link to change the page, you can see, that jQuery is calling a hashtag in the URL first. So it looks like:
example.org/page1.html#/page2.html
when I clicked on the link on page1.html (just for a few milliseconds maybe) and then it redirects to
example.org/page2.html
I guess it's because of the id .. but I need this one for the pageInit (as far as I know).
Is this behavior normal ? Or am I doing something wrong. Maybe there's even a command to not call the hash tag.
Here you go:
It's important to note that if you are linking from a mobile page that was loaded via AJAX to a page that contains multiple internal pages, you need to add a rel="external" or data-ajax="false" to the link. This tells the framework to do a full page reload to clear out the AJAX hash in the URL. This is critical because AJAX pages use the hash (#) to track the AJAX history, while multiple internal pages use the hash to indicate internal pages so there will be conflicts in the hash between these two modes.
For example, a link to a page containing multiple internal pages would
look like this:
< a href="multipage.html" rel="external">Multi-page link< /a>
Src: http://view.jquerymobile.com/1.3.0/#Linkingwithinamulti-pagedocument

Dajax example "Multiply Machine!" not working. Help

Trying to learn Dajax, so decided to try out examples. But I am stuck with the "multiply" example. I have no clue what is wrong. Below is the code.
ajax.py:(its placed inside 'blog' app)
from dajax.core import Dajax
from dajaxice.core import dajaxice_functions
def multiply(request, a, b):
dajax = Dajax()
result = int(a) * int(b)
dajax.assign('#result','value',str(result))
return dajax.json()
dajaxice_functions.register(multiply)
index.html:
{% load dajaxice_templatetags %}
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Blog</title>
{% dajaxice_js_import %}
<script type="text/javascript" charset="utf-8">
function calculate(){
Dajaxice.blog.multiply(Dajax.process,{'a':$('a').value,'b':$('b').value})
}
</script>
</head>
<body>
<input type="text" name="a" value="5" id="a"> x
<input type="text" name="b" value="6" id="b"> =
<input type="text" name="result" value="" id="result">
<input type="button" name="caculate" value="Let's Multiply!" id="caculate" onclick="calculate()">
</body>
</html>
First of all you should install dajaxice properly. Then, if you are using Dajax you should install Dajax too.
Reading your code seems that dajaxice is correctly installed but you haven't installed Dajax or (at least) you have not linked your dajax-flavoured js.
If you are using Dajax (you are using Dajax) you should choose a framework between Prototype, jQuery, Dojo or mootols and add it to your page, also you need to link the framework.dajax.core.js to your page.
The rest of the installation seems to be already done.

Resources