Flask to read and write to same csv - python

I have a flask app that was created using a csv file. Using html forms, I give the user the option to input new data, and then I write changes to the csv (using a custom function) and download it. This downloads just fine and saves to my desktop. Is there any way to tweak the code to save it in the same project directory and overwrite the csv that serves the flask app? This way the app might update upon refresh. Thanks!
#app.route('/csv/')
def download_csv():
model_id=request.args['textid']
client_id = session['client_id']
# return response
df=recommender.update_history(client_id, model_id)
df= recommender.get_csv()
resp = make_response(df.to_csv(encoding='iso-8859-1',index=False))
resp.headers["Content-Disposition"] = "attachment; filename=export.csv"
resp.headers["Content-Type"] = "text/csv"
return resp

The comment above is correct. I didn't need the make_response function. Here's what worked:
#app.route('/csv/')
def download_csv():
model_id=request.args['textid']
client_id = session['client_id']
# return response
df=recommender.update_history(client_id, model_id)
df= recommender.get_csv()
path=r'data/file_name.csv'
resp = df.to_csv(path, encoding='iso-8859-1',index=False)
return render_template('index.html')

Related

Using flask to run a python script

I have a script called output.py
This script takes in 2 inputs, fileA and file B.
I can run it on my terminal by using the command output.py -fileA -fileB. The script will create a new JSON file and save it to the directory.
I want to run this script using Flask. I've defined a bare bones App here but I'm not sure how I'd run this using Flask
from flask import Flask
import output
import scripting
app = Flask(__name__)
#app.route('/')
def script():
return output
if __name__ == '__main__':
app.run()
Can someone help me out here, thanks!
It appears you are new to Flask. Get some basic tutorials (there are many on the web).
There are a couple of options:
Send contents of file A and File b as json payload. Pull the A and B content off the json body and do the processing you need to and return the body.
Send the contents of the file as multipart/form-data (you can send multiple files).
Note: This is not working code - just for illustration.
from flask import Flask, request, make_response
app = Flask(__name__)
def build_response(status=False, error="", data={}, total=0, headers=[], contentType="application/json", expose_headers=["X-Total-Count"], retcode=400, additional_data=None):
resp = {"success": status, "error": error, "data": data}
resp = make_response(json.dumps(resp))
for item in headers:
resp.headers[item] = headers[item]
resp.headers['Content-Type'] = contentType
resp.headers.add('Access-Control-Expose-Headers', ','.join(expose_headers))
resp.status_code = retcode
return resp
#app.route('/run-script', methods=['POST'])
def run_script():
# check if the post request has the file part
try:
# Note: THis code is just to illustrate the concept.
# Option-1 (content type must be application/json)
json_dict = request.get_json()
fileA = json_dict["fileA"]
fileB = json_dict["fileB"]
# Option-2 (Note: fileA/fileB are objects, put a pdb and check it out)
fileA = request.files['fileA']
fileB = request.files['fileA']
resp = process(fileA, fileB)
return build_response(status=True, data=resp, retcode=200)
except Exception as e:
msg = f"Error - {str(ec)}"
return build_response(status=False, error=msg, retcode=400)

How to send GET/POST request on a flask based local website?

I have a website which takes a .txt file as input through an upload button. The backend model processes this text file and output a new .txt file. My website is working perfectly with the UI. But I was trying to send GET/POST request to my file using the curl command:
curl -F 'file=#CNN.txt' http://127.0.0.1:5000/
The output was that my whole html file got printed (as a cat command does) in the terminal.
I want to know how can I get the processed file using the curl command itself? I think to get the file, I need to return some kind of JSON object too. I am completely new to this stuff. Please bare with me.. My appy.py file is:
#app.route('/', methods = ['GET','POST'])
def hello():
if(request.method == 'POST'):
if('file' not in request.files):
return 'NO FILE'
file = request.files['file']
if(file.filename == ''):
print('NO FILES')
return redirect(request.url)
if(file and allowed_file(file.filename)):
uploadedFile = file.filename
file.save(os.path.join(UPLOAD_FOLDER, file.filename))
if(uploadedFile != ''):
neural_code_sum.starter(uploadedFile)
return render_template('index.html', message='success')
return render_template('index.html', message='NOT UPLOADED (ONLY .TXT FILES ALLOWED)')
#app.route('/download')
def download_file():
global uploadedFile
doc = os.path.dirname(os.path.realpath(__file__))+'/output.txt'
return send_file(doc,as_attachment=True,cache_timeout=0)
Just add GET above:
#app.route('/download', methods = ['GET'])
def download_file():
global uploadedFile
doc = os.path.dirname(os.path.realpath(__file__))+'/output.txt'
return send_file(doc,as_attachment=True,cache_timeout=0)
The first send the file: curl -F 'file=#CNN.txt' http://127.0.0.1:5000/
Then download it: curl http://127.0.0.1:5000/download -o output.txt
That's it! All the best.
#app.route('/download',methods=['**GET'**])
def download_file():
global uploadedFile
doc = os.path.dirname(os.path.realpath(__file__))+'/output.txt'
return send_file(doc,as_attachment=True,cache_timeout=0)
Add the method by which you want to send the request in the methods field.

send, receive, save local image file with requests / django rest framework

I'd like to http-send (e.g. requests.post) image files from servers/clients (with the requests lib) and receive/save these files with a django rest framework app. How do I do this?
Secondly I'd like to know how to extract parts from a QueryDict sent by requests.post in general. And more specific: How do I parse and save the _io-Object from this set of data?
# sending app
file = "path/to/image.jpg"
data = open(file, 'rb')
files = {
'json': (None, crawlingResultConnectionsJson, 'application/json'),
'file': (os.path.basename(file), open(file, 'rb'), 'application/octet-stream')
}
url = "http://127.0.0.1:8000/result/" # receiving/saving django rest framework app
r = requests.post(url, files=files)
I've tried quite a while now. Your help would be much appreciated! Thanks!
I came to a solution that perfectly fits my needs. As I only found contributions for either the sending OR the receiving part, I'll try to put everything together here.
Due to more flexibility my approach is to transfer json and images in seperated requests. The two following apps are completely independent.
The sending side does as follows (app with no server needed):
from django.core.serializers.json import DjangoJSONEncoder
import requests # http://docs.python-requests.org/en/master/
import datetime # in case...
import json
### send image stuff ###
urlImages = "http://127.0.0.1:8000/receive-images/"
file = "C:\\path\\to\\filename.jpg" # "\\" windows machine...
# this will probably run in a loop or so to process a bunch of images
with open(file, 'rb') as f:
filename = "filename.jpg"
files = {'file': (filename, f)}
r = requests.post(urlImages, files=files)
print(r) # some logging here
### send data stuff ###
data = data # python data - lists, dicts, whatever
json = json.dumps(data, cls=DjangoJSONEncoder) # DjangoJSONEncoder handles datetime fields
urlData = "http://127.0.0.1:8000/receive-data/"
headers = {'content-type': 'application/json'}
r = requests.post(urlData, json, headers=headers)
print(r) # some logging here
The receiving side needs to run a server (built-in django server for dev, apache with the WSGInterface in production) and it has this chum installed: http://www.django-rest-framework.org/
Finally we have two views to handle the requests:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .api_controller import ApiController
from django.core.files.storage import default_storage
class ReceiveImages(APIView): # make sure to nail down corresponding url-confs
def post(self, request, format=None):
file = request.data.get('file')
filename = str(file)
with default_storage.open('images/' + filename, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
return Response("ok", status=status.HTTP_200_OK)
class ReceiveData(APIView): # make sure to nail down corresponding url-confs
def post(self, request, format=None):
json = request.data
ApiController().createDataIfNotExists(json)
# As my json is quite complex,
# I've sourced out the DB-interactions to a controller-like class (coming
# from PHP symfony :)) with heavy use of the great
# MyModel.objects.get_or_create() method. Also the strptime() method is used
# to convert the datetime fields. This could also go here...
return Response("ok", status=status.HTTP_200_OK)
using chunk() in respect to https://stackoverflow.com/a/30195605/6522103
Please (!) comment/answer if you don't agree or think that this could be improved. Thanks!!

How to test send_file flask

I have a small flask application which takes some images for upload and converts them into a multipage tiff. Nothing special.
But how do I test the upload of multiple files and the file download?
My Testclient:
class RestTestCase(unittest.TestCase):
def setUp(self):
self.dir = os.path.dirname(__file__)
rest = imp.load_source('rest', self.dir + '/../rest.py')
rest.app.config['TESTING'] = True
self.app = rest.app.test_client()
def runTest(self):
with open(self.dir + '/img/img1.jpg', 'rb') as img1:
img1StringIO = StringIO(img1.read())
response = self.app.post('/convert',
content_type='multipart/form-data',
data={'photo': (img1StringIO, 'img1.jpg')},
follow_redirects=True)
assert True
if __name__ == "__main__":
unittest.main()
The application sends back the file with
return send_file(result, mimetype='image/tiff', \
as_attachment=True)
I want to read the file sent in the response and compare it with another file. How do I get the file from the response object?
I think maybe the confusion here is that response is a Response object and not the data downloaded by the post request. This is because an HTTP response has other attributes that are often useful to know, for example http status code returned, the mime-type of the response, etc... The attribute names to access these are listed in the link above.
The response object has an attribute called 'data', so response.data will contain the data downloaded from the server. The docs I linked to indicate that data is soon to be deprecated, and the get_data() method should be used instead, but the testing tutorial still uses data. Test on your own system to see what works.Assuming you want to test a round trip of the data,
def runTest(self):
with open(self.dir + '/img/img1.jpg', 'rb') as img1:
img1StringIO = StringIO(img1.read())
response = self.app.post('/convert',
content_type='multipart/form-data',
data={'photo': (img1StringIO, 'img1.jpg')},
follow_redirects=True)
img1StringIO.seek(0)
assert response.data == imgStringIO.read()

How to download several files with GAE Python

I'd like to download several files with GAE Python code.
My current code is like below
import webapp2, urllib
url1 = 'http://dummy/sample1.jpg'
url2 = 'http://dummy/sample2.jpg'
class DownloadHandler(webapp2.RequestHandler):
def get(self):
#image1
self.response.headers['Content-Type'] = 'application/octet-stream'
self.response.headers['Content-Disposition'] = 'attachment; filename="' + 'sample1.jpg' + '"'
f = urllib.urlopen(url1)
data = f.read()
self.response.out.write(data)
#image2
self.response.headers['Content-Type'] = 'application/octet-stream'
self.response.headers['Content-Disposition'] = 'attachment; filename="' + 'sample2.jpg' + '"'
f = urllib.urlopen(url2)
data = f.read()
self.response.out.write(data)
app = webapp2.WSGIApplication([('/.*', DownloadHandler)],
debug=True)
I expected to occur download dialogue twice with this code, but actually occurred once, and only sample2.jpg was downloaded.
How can you handle download dialogue several times?
I'd actually like to realize some other functions adding above as well.
To display progressing message on the browser such as
sample1.jpg was downloaded
sample2.jpg was downloaded
sample3.jpg was downloaded ...
And redirect to the other page after downloading files.
When I wrote a code such as
self.redirect('/otherpage')
after
self.response.out.write(data)
Only redirect had happened and didn't occur download procedure.
Would you give me any ideas to solve it please.
I'm using python2.7
Two things.
You cannot write two files in one response that has a Content-Type of application/octet-stream. To stuff multiple files in in the response, you would have to encode your response with multipart/form-data or multipart/mixed and hope that the client would understand that and parse it and show two download dialogues
Once you've already called self.response.out.write(…), you shouldn't be setting any more headers.
To me it seems that the most foolproof option would be to serve an HTML file that contains something like:
<script>
window.open('/path/to/file/1.jpg');
window.open('/path/to/file/1.jpg');
</script>
… and then handle those paths using different handlers.
Another option would be to zip the two files and serve the zipfile to the client, though it may or may not be preferable in your case.
I reached the goal what I wanted to do.
As user interaction, generating html sources include below
<script type="text/javascript">
window.open("/download?url=http://dummy/sample1.jpg")
window.open("/download?url=http://dummy/sample2.jpg")
</script>
then created new windows are handled with this code.
class DownloadHandler(webapp2.RequestHandler):
def get(self):
url = self.request.get('url')
filename = str(os.path.basename(url))
self.response.headers['Content-Type'] ='application/octet-stream'
self.response.headers['Content-Disposition'] = 'attachment; filename="%s"' % (filename)
data = urllib.urlopen(url).read()
self.response.out.write(data)
app = webapp2.WSGIApplication([('/download', DownloadHandler)], debug=True)
Thank you, Attila.

Categories

Resources