I have been prototyping a web server using flask and recently switched to ReactJS for my front end. I am trying to display an image that is stored on my server to my web page as follows:
#app.route("/graph" methods=['POST'])
def displayGraph():
return send_from_directory("graphDir", "graph.png")
Before switching to React, if I went to /graph, the image would display no problem. Now, however, the webpage never redirects to /graph and displays the byte code for the image instead of the image itself. What do I need to change to properly display my image on my React web page? For reference, my React code is below:
export default class App extends React.Component {
constructor (props) {
super(props);
//Initialize your state here
this.state = {
results: "",
};
//bind functions here
this.handleChange = this.handleChange.bind(this);
}
//this is called after everything is created
componentDidMount() {
}
//add functions here
//changes state of checkbox
handleChange(event) {
const value = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
this.setState({
[event.target.name]: value
});
}
submit() {
$.ajax({
type: "POST",
contentType: "application/json",
url: "/graph",
});
}
render() {
return (
<div>
<div className="big title">Title</div>
<input type="button" onClick={() => this.submit()} value="Submit" className="button"/>
</div>
);
}
}
If you are able to get the byte code of the image using the ajax call, you can add an <img> to your render and set the src to the image's byte code.
<image src = 'data:image/jpeg;base64,' + 'your-image-data'/>
Related
I am trying to connect my flask api to my react app and all I want from that is to display the string I returned from the flask on react app.
In doing so, I used useEffect(), but my variable in react is not changed but just keeps the original state. When I use console.log to see the value that I am passing to the variable, it shows an error saying "Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0".
App.js looks like:
import React, {Component, useState, useEffect} from 'react';
import './App.css';
function App() {
const [block, setBlock] = useState(0);
useEffect(() => {
fetch('/video').then(res => res.json()).then(data => {
setBlock(data.text);
console.log(data.text);
});
}, []);
return (
<div className="App">
<header className="App-header">
<p>Text: {block}</p>
</header>
</div>
);
}
export default App;
part of flask(flask.py):
#app.route('/video')
def video():
return {'text': text}
Any insight would be greatly appreciated!
If you want to return JSON from a Flask route use flask.jsonify.
from flask import jsonify
#app.route('/video')
def video():
return jsonify({'text': text})
I edited my code on this question based on comments of #dirkgroten, Thanks!
In my web site, a submitted image is sent to Django view.
In Django, the image is processed for reducing the size and returned using JsonResponse.
What I want to do is to return the data(binary image) as 'multipart/form-data'format.
Previously my code can upload original photo.
Now I'm adding the size reducing function.
My previous code already works well with the data, multipart/form-date format from html. So I want to keep using the previous code and just add the size reducing function.
How Can I return the data as 'multipart/form-data' in django view?
Here is code.
view.py
#login_required
#user_passes_test(customer_check)
def receipt_reduce_size(request):
if request.method == 'POST':
from django.core.files.uploadedfile import InMemoryUploadedFile
from io import BytesIO
from PIL import Image as pil
import base64
import sys
# get image file
imageFile = request.FILES.get("file")
input_file = BytesIO(imageFile.read()) # as binary
# size reducing process below
img = pil.open(input_file)
image_file = BytesIO()
img.save(image_file, format="jpeg", quality=80, optimize=True) # reduced file is saved to 'image_file'
contents = image_file.getvalue() # the binary value of image_file is save to contents
encoded = base64.b64encode(contents) # the binary is encoded with base64
data = encoded.decode('ascii') # and decoded with ascii, so it's now string
return JsonResponse({'status':'success', 'data':data})
return JsonResponse({'status': 'fail'})
site.html
In the code, var file(multipart/form-data) is what I used. I want to return the same data format with the file from receipt_reduce_size function of view.py.
<form id="register-submit-form" enctype="multipart/form-data">
{% csrf_token %}
<div class="doctor-info-input form-group mdd-event-wrapper">
<label for="image" class="control-label">please upload image</label>
<img src="{% static 'img/event/receipt_example.png' %}" style="width: 80%;margin-top: 20px;">
<input id="image" name="image" type="file" >
<input type="hidden" id="image_url" name="image_url">
</div>
<button class="btn" type="submit" style="width: 100%;margin-top:20px;">image submit</button>
</form>
<script>
$('#register-submit-form').on('submit', function(e) {
e.preventDefault();
var files = $('#image')[0].files;
var file = files[0]; // This 'file' is what I used.
if(!file){
return alert("please submit again!");
}
// image submit start
$.ajax({
url: "{% url 'event:s3_direct_upload' %}?file_name=" + file.name + '&file_type=' + file.type,
//this api return file path and s3 authorization key
type: 'GET',
cache: false,
success: function(data){
var response = data;
var postData = new FormData();
for(key in response.data.fields){
postData.append(key, response.data.fields[key]);
}
var image_new_name = response.image_new_name;
var postDataUnreduced = new FormData();
postDataUnreduced.append('file', file);
postDataUnreduced.append('image_new_name', image_new_name);
// reduce image file size
$.ajax({
url: "{% url 'event::image_reduce_size' %}",
type: 'POST',
enctype: 'multipart/form-data',
cache: false,
processData: false,
contentType: false,
data: postDataUnreduced,
success: function(data) {
postData.append('file', data);
// upload image file
$.ajax({
url: response.data.url, // this is https://my-site-staticfiles.s3.amazonaws.com/ So, AWS S3 api.
type: 'POST',
processData: false,
contentType: false,
data: postData,
success: function(data, textStatus, xhr) {
},
complete: function() {
},
error: function(jqXHR, textStatus, errorThrown) {
}
});
},
error: function(){
alert('error')
}
})
},
complete: function() {
},
error: function(jqXHR, textStatus, errorThrown) {
}
});
});
</script>
When I run my code, what I got in my web are these.
image in my web
when I click the image link, black.
I'm using Django 1.11(not 1.1, sorry for confusing!), Python3.6.7, jQuery and ajax for request and get the response.
I am trying to run and display some simple python code and was hoping I could use the python-shell package. Is it possible to run the package with react js?
I have a code sandbox below. Is there a way to run the simple "x=1+1;print(x)" script when the button is clicked?
CodeSandbox:
https://codesandbox.io/s/little-meadow-wlni3
Here is the Code.js file:
import React, { Component } from "react";
import { PythonShell } from "python-shell";
export default class Code extends Component {
render() {
function runPython() {
PythonShell.runString("x=1+1;print(x)", null, function(err) {
if (err) throw err;
console.log("finished");
});
}
return (
<>
<div className="output">code goes here</div>
<button type="button" onClick={runPython}>
Run
</button>
</>
);
}
}
ended up creating an express.js backend api and ran it through there to process the python and then sent the output to the react client side.
my bottle app.py looks something like:
#route('/submit/<var>')
def submit(var):
# do action
redirect("/")
and i have a simple html button which redirects to the required page when clicked through
onclick="window.location.href='/submit/value'"
but this causes the whole page to effectively refresh by going to the link and then coming back straight away, putting the user to the top of the page and so on.
How can i get it to do the bottle backend without refreshing?
In your template:
<button type="button" onclick="onSubmit('Value')">Sumbit!</button>>
<p id="response"></p>
<script>
function onSubmit(value) {
var myRequest = new Request('/submit/' + value);
var myInit = { method: 'PUT' };
fetch(myRequest, myInit).then(function(response) {
return $("#response").text(response);
});
}
</script>
In the python side
#put("/submit/<val>")
def submit(val):
return "Yay it worked!"
I'm looking to display a constantly-changing python variable (that's read from a websocket server) onto a HTML file, currently i'm using a Django tag as it follows:
templatetags/mytag.py
from django import template
register = template.Library()
current_value = 0
#register.filter
def c_value(placeholder):
return current_value
#more code that modifies current_value reading from a websocket server
index.html
{% load mytag %}
<script>
function mytimer() {
setInterval(function(){
$('#stuff').html( {{ placeholder|c_value }} );
}
, 1000);
}
mytimer();
</script>
#some code from the website
<span id="stuff">Holder</span>
However naturally '{{ placeholder|c_value }}' only outputs the first ever value of 'current_value', which is 0 in this case, and so the source code of index.html ends up being:
source code after '{{ placeholder|c_value }}'
<script>
function mytimer() {
setInterval(function(){
$('#stuff').html( 0 );
}
, 1000);
}
mytimer();
</script>
Which is not desired since we would like to print the changing-value of 'current_value' each second.
What is the normal approach for these kind of dynamic texts? Many thanks!
There are a few things you'll need to do to accomplish this behavior.
Set up a URL that returns the value you're interested in. For instance, set up your website so that the URL http://example.com/c_value returns a response with the correct information. It's usually a good idea to return the response in a JSON format; in Django, you can use the JsonResponse class to do this. Suppose you return the text:
{
"c_value": "foo"
}
Change your page so that instead of loading in a variable from a template, it makes a request to the address that you set up. If you're using jQuery, you can use the $.ajax function to do this (or $.getJSON, which is just a shorthand function for $.ajax with only JSON data). You'll probably end up with something like this inside of your timer, assuming that the JSON returned matches the example I gave in step 1. (data will contain the JSON object that you sent from the server).
$.ajax({
dataType: "json",
url: "http://example.com/c_value",
success: function(data) {
$('#stuff').html(data["c_value"]);
}
});