How do I take a mongodb json to flask to react? - reactjs

So I want to take my mongo db and use it in react, its small so it won't overpower react. My Flask looks like this
import subprocess
from flask import Flask, request, jsonify, json
from flask_cors import CORS, cross_origin
import pymongo
disaster = ""
app = Flask(__name__)
CORS(app, support_credentials=True)
client = pymongo.MongoClient("NOT IMPORTANT FOR GITHUB")
db = client["twitterdb"]
col = db["tweets"]
our_mongo_database_compressed = col.find({},{'user.created_at':1, 'user.location':1,'_id':0})
def request_tweets(disaster):
print(disaster)
#subprocess.call("./../../../backend/get_tweets", disaster)
#app.route('/refresh_data', methods=['GET', 'POST'])
##cross_origin(supports_credentials=True)
def refresh_data():
disaster = request.get_json()
request_tweets(disaster)
x = 0
y = []
for datas in our_mongo_database_compressed:
y.append(datas)
if(x > 100):
break
x+=1
#print(y)
return str(y)
and my react function looks like
this.setState({
disaster: event.target.value
})
axios.post('http://localhost:5000/refresh_data', [this.state.disaster])
.then(function(response){
console.log(JSON.parse(response.data));
})
}
I keep getting a " Unexpected token ' in JSON at position 2" and I just want the data to be sent to react

So I figured it out and I want anyone who has this problem in the future to be able to see this.
for datas in our_mongo_database_compressed:
y.append(datas)
This creates an array of dictionaries. so y[0]["user"]["location"] would be how you'd get an element from this array.
With that in mind we need to change this array to a JSON String which is a data type that you use to transfer between flask and react so you'd return
return json.dumps(y)
Now you might think this means that you got a string in React when you write
JSON.parse(response.data)
NO. That would be too easy, you have a response object that secretly a string. So you'd need to change the response object into a string with JSON stringify
JSON.parse(JSON.stringify(response.data))
Now you have your json in react

Related

axios cannot get only response of base64 but can get the others data

First, I sent an image path from react to Django by using the axios of POST method.
Next, I edited the image in Django, and returned edited images that were converted into base64 to react.
like this.
/* this is view.py in Django */
class SquareCognitionSet(viewsets.ViewSet):
#action(methods=['POST'], detail=False, name='Edit image')
def show(self, request):
input = request.data['input']
edited_image = edit.main(input) // my user-defined function. return base64 after edit image.
data = {"message": "Got base64", "base": edited_image, "type": imghdr.what(input)}
return Response(data=data)
No problem so far.
Promlem is from here.
I cannot get only base64 data of response that was sent from Django.
However, axios could get response from Django. I confirmed console.log()
/*this is react*/
useEffect(()=>{
async function check(ImagePath: string) {
window.electronAPI.server_on(); // electron starts server to work axios
await axios.post("http://127.0.0.1:8000/ImageEdit/edit/", {
input: ImagePath // input value of image path
})
.then((response)=>{
console.log("success: ", response); // <-- here, I confirmed response
})
this is result of console.log().
Then I run
console.log("base64: ", response.data.base);
However, nothing is shown. Even the text of "base64: " is disappear.
What I tried.
I tried whether I can take out the others value sent from Django.
I added value {"message": "Got base64"} in response of Django.
Then, I take out value like
console.log("message: ", response.data.message);
console.log("status: ", response.status);
They are successfuly shown. So, This may be problem of base64.
I confirmed capacity in POST method
I checked the length of base64 in Django. This was 34789440.
So, I made string value that has length of 40000000: t = "A"410**7
Then, I added this into response in Django, and I could receive it successfully in react.
convert to JSON before being sent from Django
I added the following code into view.py in Django.
...
data = {"message": "Got base64", "base": edited_image, "type": imghdr.what(input)}
params = json.dumps(data)
return Response(data=data)
The result was almost same the above my problem. console.log("success: ", response); showed
However, all response data became undefined. Even response.status became undefined.
check type of data
base64 was 'str'.
Why couldn't I take out only base64???
I googled it including how to use axios, Django post method and so on.
But I don't know how to fix it.
Thanks in advance.

Sending a file from Flask using send_file to a React frontend returns a string of weird characters

In my current program, the user selects a file in react, which is sent to flask as such
return axios
.post(`http://localhost:5000/time`, data, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
.then(res => {
this.onReturnProcessed(res);
return res
});
}
and recieves data from flask as such
onReturnProcessed = res =>{
console.log((res.data))
this.setState({img:res.data})
this.setState({ImgReturned:true})
}
The Flask backend takes these files, and makes them a numpy array, and then a PIL Image object. It then saves the Image object to the Flask folder as such
img = Image.fromarray((np.uint8(cm(img)*255)))
img.save("./thenewimg.png")
Flask then sends the file to the react frontend
return send_file('./thenewimg.png',mimetype = 'image/png',as_attatchment=True)
The problem is that when React renders the file sent by flask
render(){
<div>
<img src = {this.state.img}/>
</div>
}
it is unable to interpret the file, and displays nothing except the file icon in the corner. When the file sent by flask is logged, it outputs many characters like ���}>�{���o��n�_����|��t����Jm~�\Ӳ���. I'm not sure how to change the file on the python backend so that react can interpret it and display it. Otherwise, I'm not sure how to change the frontend to display an image made in python.
This worked
#app.route('/img/<filename>',methods = ['GET'])
def give(filename):
filen = './UPLOADS/'+filename+'.png'
return send_file(filen)
I believe what is happening here is you are assigning res.data to your img variable. res.data is not the image itself that is assigned to var, but instead its base64 representation. This is why you are seeing the weird characters instead of the actual image.
An easier way to accomplish what you want might be to send back the URL of the image, not the image itself. This way you can store the image URL in your string, and then present the image like so:
console.log(this.state.img); // <-- this now returns 'https://whateveryourapiaddris.com/img/ID'
...
<img src={this.state.img} />
This means that you will need to create a separate flask route that will ingest the image ID that you assign to the image, and return the corresponding image using send_file at that end point.
Related questions:
How to get the image response from a Flask api server and then display it in a react application
https://www.reddit.com/r/reactjs/comments/bifsrt/display_image_from_flask_send_file_function/

Flask only accept single json variable and crashed when setting two variables

I am building a web crawler app on Google App Engine. I want to use a post method to pass the variable to Flask. Then, the received variable became the input of my web crawler app. However, Flask only accept single variable from post. If I add another variable in the funciton, Flask would crash.
I have limited knowledge in Flask and Google app engine. I struggled with the problem for several days and your help will be highly appreciated.
Failed function
#server-side function that does not work,with 2 variable passed
#app.route('/bac',methods=['GET', 'POST'])
def bac():
request_json = request.get_json()
filename = request_json["filename"]
url = request_json["url"]
#baseconnect.Baseconnect(url=url,filename=filename).run()
return filename,url
#The function to post on client side
import requests
req = requests.Session()
data = req.post('https://project.appspot.com/bac',json={"filename":"yuan","url":"https:...f5"})
print(data.text)
#output:
Internal server eror 500
Succeeded function
#server-side function that works,with 1 variable passed
#app.route('/bac',methods=['GET', 'POST'])
def bac():
request_json = request.get_json()
filename = request_json["filename"]
#url = request_json["url"]
#baseconnect.Baseconnect(url=url,filename=filename).run()
return filename
#The function to post on client side
import requests
req = requests.Session()
data = req.post('https://project.appspot.com/bac',json={"filename":"yuan"})
print(data.text)
#output:
yuan
Flask seems only accept single variable. What is the problem....
The problem you have here is that Flask only returns Response object, and Flask will consider return filename, url a shortcut of return Response, status or header.
In this case, url becomes the http status code or header, which is obviously not right.
You need flask.jsonify() to return the proper format of so called 'multiple variables'.
Something like this: (only the important part)
# In server-side code
from flask import jsonify
#app.route('/bac',methods=['GET', 'POST'])
def bac():
request_json = request.get_json()
filename = request_json["filename"]
url = request_json["url"]
# Do your logic here
return jsonify({ filename_returned: filename, url_returned: url })
# client-side
import requests
req = requests.Session()
json_data = req.post('https://project.appspot.com/bac',json={"filename":"yuan", "url": "http:xxxxxxx"})
real_data = json.loads(json_data)
# real_data should be the result you want

Google App Engine + Flask + Stripe: Attribute Error: AttributeError: 'function' object has no attribute 'Customer'

I'm starting a mini blog for my honeymoon with Google App Engine, Flask and Stripe that we can send to family and friends. Everythings working great, except for Stripe.
Error Received:
File "/Users/MDev/Desktop/Steph_Max/Wedding/main.py", line 131, in charge
customer = stripe.Customer.create(
AttributeError: 'function' object has no attribute 'Customer'
This is the code line it's referring to in the error.
#app.route('/stripe')
def stripe():
return render_template('stripe.html', key=stripe_keys['publishable_key'])
#app.route('/charge', methods=['POST'])
def charge():
# Amount in cents
amount = 500
customer = stripe.Customer.create(
email = 'customer#example.com',
card = request.form['stripeToken']
)
charge = stripe.Charge.create(
customer=customer.id,
amount=amount,
currency='usd',
description='Flask Charge'
)
return render_template('charge.html', amount=amount)
I have my main.py setup with just the default checkout as documented in Stripe docs:
from flask import Flask
from flask import render_template, request, redirect, url_for
from werkzeug.utils import secure_filename
from flask import send_from_directory
import stripe
import os
app = Flask(__name__)
#app.config['DEBUG'] = True
stripe_keys = {
'secret_key' : os.environ['SECRET_KEY'],
'publishable_key' : os.environ['PUBLISHABLE_KEY']
}
stripe.api_key = stripe_keys['secret_key']
My index page works (I've renamed it stripe.html) but the issue is just when it goes to the charge page. The script for the stripe button is working, I can submit a fake card, everything works except unto the charge page.
I'm on the noob side of noob so please be patient with me and if I'm missing something I'll update ASAP :)
Versions:
stripe: stripe-1.14.0-py2.7.egg-info
Python: 2.7
GAE: 1.9.3
The problem is you have imported the stripe library and then defined a function with the same name.

<class 'google.appengine.runtime.DeadlineExceededError'>: how to get around?

Ok guys I am having tons of problems getting my working dev server to a working production server :). I have a task that will go through and request urls and collect and update data. It takes 30 minutes to run.
I uploaded to production server and going to the url with its corresponding .py script appname.appspot.com/tasks/rrs after 30 seconds I am getting the class google.appengine.runtime.DeadlineExceededError' Is there any way to get around this? Is this a 30 second deadline for a page? This script works fine in development server I go to the url and the associate .py script runs until completion.
import time
import random
import string
import cPickle
from StringIO import StringIO
try:
import json
except ImportError:
import simplejson as json
import urllib
import pprint
import datetime
import sys
sys.path.append("C:\Program Files (x86)\Google\google_appengine")
sys.path.append("C:\Program Files (x86)\Google\google_appengine\lib\yaml\lib")
sys.path.append("C:\Program Files (x86)\Google\google_appengine\lib\webob")
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class SR(db.Model):
name = db.StringProperty()
title = db.StringProperty()
url = db.StringProperty()
##request url and returns JSON_data
def overview(page):
u = urllib.urlopen(page)
bytes = StringIO(u.read())
##print bytes
u.close()
try:
JSON_data = json.load(bytes)
return JSON_data
except ValueError,e:
print e," Couldn't get .json for %s" % page
return None
##specific code to parse particular JSON data and append new SR objects to the given url list
def parse_json(JSON_data,lists):
sr = SR()
sr.name = ##data gathered
sr.title = ##data gathered
sr.url = ##data gathered
lists.append(sr)
return lists
## I want to be able to request lets say 500 pages without timeing out
page = 'someurlpage.com'##starting url
url_list = []
for z in range(0,500):
page = 'someurlpage.com/%s'%z
JSON_data = overview(page)##get json data for a given url page
url_list = parse_json(JSON_data,url_list)##parse the json data and append class objects to a given list
db.put(url_list)##finally add object to gae database
Yes, the App Engine imposes a 30 seconds deadline. One way around it might be a try/except DeadlineExceededError and putting the rest in a taskqueue.
But you can't make your requests run for a longer period.
You can also try Bulkupdate
Example:
class Todo(db.Model):
page = db.StringProperty()
class BulkPageParser(bulkupdate.BulkUpdater):
def get_query(self):
return Todo.all()
def handle_entity(self, entity):
JSON_data = overview(entity.page)
db.put(parse_json(JSON_data, [])
entity.delete()
# Put this in your view code:
for i in range(500):
Todo(page='someurlpage.com/%s' % i).put()
job = BulkPageParser()
job.start()
ok so if I am dynamically adding links as I am parsing the pages, I would add to the todo queue like so I believe.
def handle_entity(self, entity):
JSON_data = overview(entity.page)
data_gathered,new_links = parse_json(JSON_data, [])##like earlier returns the a list of sr objects, and now a list of new links/pages to go to
db.put(data_gathered)
for link in new_links:
Todo(page=link).put()
entity.delete()

Resources