pytest-django how test excel response [duplicate] - django

Right now I'm just checking the response of the link like so:
self.client = Client()
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
Is there a Django-ic way to test a link to see if a file download event actually takes place? Can't seem to find much resource on this topic.

If the url is meant to produce a file rather than a "normal" http response, then its content-type and/or content-disposition will be different.
the response object is basically a dictionary, so you could so something like
self.assertEquals(
response.get('Content-Disposition'),
"attachment; filename=mypic.jpg"
)
more info:
https://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment
UPD:
If you want to read the actual contents of the attached file, you can use response.content. Example for a zip file:
try:
f = io.BytesIO(response.content)
zipped_file = zipfile.ZipFile(f, 'r')
self.assertIsNone(zipped_file.testzip())
self.assertIn('my_file.txt', zipped_file.namelist())
finally:
zipped_file.close()
f.close()

Related

Django, Store jpg file received as string in http POST

I am receiving an http request from a desktop application with a screenshot. I cannot speak with the developer or see source code, so all I have is the http request I am getting.
The file isn't in request.FILES, it is in request.POST.
#csrf_exempt
def create_contract_event_handler(request, contract_id, event_type):
keyboard_events_count = request.POST.get('keyboard_events_count')
mouse_events_count = request.POST.get('mouse_events_count')
screenshot_file = request.POST.get('screenshot_file')
barr2 = bytes(screenshot_file.encode(encoding='utf8'))
with open('.test/output.jpeg', 'wb') as f:
f.write(barr2)
f.close()
The file is corrupted.
The binary starts like this, I don't know if that helps:
����JFIFHH��C
%# , #&')*)-0-(0%()(��C
(((((((((((((((((((((((((((((((((((((((((((((((((((�� `"��
Also, if I try to open the image with PIL, I get the following error:
from PIL import Image
im = Image.open('./test/output.jpg')
#OSError: cannot identify image file './test/output.jpg'
Finally, I managed to touch the code in the other hand, the 'filename' was missing in the header and for that reason I was getting the file in the POST instead of in the FILES dictionary.

Why does the Python script to send data to Slack web hook not work when variable is pulled from a line?

Language: Python 2.7
Hello all. I found a really helpful script here: Python to Slack Web Hook
that shows how to send messages to a Slack web hook.
import json
import requests
# Set the webhook_url to the one provided by Slack when you create the webhook at https://my.slack.com/services/new/incoming-webhook/
webhook_url = 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
slack_data = {"text": "<https://alert-system.com/alerts/1234|Click here> for details!"}
response = requests.post(
webhook_url, data=json.dumps(slack_data),
headers={'Content-Type': 'application/json'}
)
if response.status_code != 200:
raise ValueError(
'Request to slack returned an error %s, the response is:\n%s'
% (response.status_code, response.text)
)
It works flawlessly when I run .py file.
Now, I have a file that has many lines of messages that I want to send to Slack. I have it formatted correctly already in the file, no spaces etc.. It's just a matter of grabbing it and passing it so slack_data = line1 etc..
So, I modify the file with something like this:
with open('export.txt', 'r') as e:
for line in e:
slack_data = line
Now if I do a print slack_data right after that, the information returns on the screen exactly as it should be, so I'm thinking it's good. I haven't began to get it working for each line yet, because it's not even working on the first line.
I get an invalid payload 400 when I run it.
EDIT: Slack support said the what they were receiving has escape characters inserted into for some reason.
"{\"text\": \"<https://alert-system.com/alerts/1234|Click here> for details!"}\n"
Any direction or assistance is appreciated.
Thanks!!
Just posting as it might help somebody. For me the below snippet worked:
data = json.dumps(slack_data)
response = requests.post(
URL, json={"text": data},
headers={'Content-Type': 'application/json'}
)
As #Geo pointed out the final payload that we are going to send should have keyword "text", else it will fail.
Moreover, in post method I have to replace data= with json= else it kept throwing error for invalid payload with 400
Since I already had the data preformatted in the file as JSON already, it was just a matter of removing json.dumps out of the code.
OLD:
#response = requests.post(webhook_url, data=json.dumps(slack_data), headers={'Content-Type': 'application/json'})
NEW:
response = requests.post(webhook_url, data=slack_data, headers={'Content-Type': 'application/json'})
Once I did that, everything worked like a charm.
If you change the code to this:
with open('export.txt', 'r') as e:
slack_data = e.read()
do you still get the 400?

Django to serve generated excel file

I looked at the various questions similar to mine, but I could not find anything a fix for my problem.
In my code, I want to serve a freshly generated excel file residing in my app directory in a folder named files
excelFile = ExcelCreator.ExcelCreator("test")
excelFile.create()
response = HttpResponse(content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="test.xls"'
return response
So when I click on the button that run this part of the code, it sends to the user an empty file. By looking at my code, I can understand that behavior because I don't point to that file within my response...
I saw some people use the file wrapper (which I don't quite understand the use). So I did like that:
response = HttpResponse(FileWrapper(excelFile.file),content_type='application/vnd.ms-excel')
But then, I receive the error message from server : A server error occurred. Please contact the administrator.
Thanks for helping me in my Django quest, I'm getting better with all of your precious advices!
First, you need to understand how this works, you are getting an empty file because that is what you are doing, actually:
response = HttpResponse(content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="test.xls"'
HttpResponse receives as first arg the content of the response, take a look to its contructor:
def __init__(self, content='', mimetype=None, status=None, content_type=None):
so you need to create the response with the content that you wish, is this case, with the content of your .xls file.
You can use any method to do that, just be sure the content is there.
Here a sample:
import StringIO
output = StringIO.StringIO()
# read your content and put it in output var
out_content = output.getvalue()
output.close()
response = HttpResponse(out_content, mimetype='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="test.xls"'
I would recommend you use:
python manage.py runserver
to run your application from the command line. From here you will see the console output of your application and any exceptions that are thrown as it runs. This may provide a quick resolution to your problem.

Django Unit Test for testing a file download

Right now I'm just checking the response of the link like so:
self.client = Client()
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
Is there a Django-ic way to test a link to see if a file download event actually takes place? Can't seem to find much resource on this topic.
If the url is meant to produce a file rather than a "normal" http response, then its content-type and/or content-disposition will be different.
the response object is basically a dictionary, so you could so something like
self.assertEquals(
response.get('Content-Disposition'),
"attachment; filename=mypic.jpg"
)
more info:
https://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment
UPD:
If you want to read the actual contents of the attached file, you can use response.content. Example for a zip file:
try:
f = io.BytesIO(response.content)
zipped_file = zipfile.ZipFile(f, 'r')
self.assertIsNone(zipped_file.testzip())
self.assertIn('my_file.txt', zipped_file.namelist())
finally:
zipped_file.close()
f.close()

django return file over HttpResponse - file is not served correctly

I want to return some files in a HttpResponse and I'm using the following function. The file that is returned always has a filesize of 1kb and I do not know why. I can open the file, but it seems that it is not served correctly. Thus I wanted to know how one can return files with django/python over a HttpResponse.
#login_required
def serve_upload_files(request, file_url):
import os.path
import mimetypes
mimetypes.init()
try:
file_path = settings.UPLOAD_LOCATION + '/' + file_url
fsock = open(file_path,"r")
#file = fsock.read()
#fsock = open(file_path,"r").read()
file_name = os.path.basename(file_path)
file_size = os.path.getsize(file_path)
print "file size is: " + str(file_size)
mime_type_guess = mimetypes.guess_type(file_name)
if mime_type_guess is not None:
response = HttpResponse(fsock, mimetype=mime_type_guess[0])
response['Content-Disposition'] = 'attachment; filename=' + file_name
except IOError:
response = HttpResponseNotFound()
return response
Edit:
The bug is actually not a bug ;-)
This solution is working in production on an apache server, thus the source is ok.
While writing this question I tested it local with the django development server and was wondering why it does not work. A friend of mine told me that this issue could arise if the mime types are not set in the server. But he was not sure if this is the problem. But one thing for sure.. it has something to do with the server.
Could it be that the file contains some non-ascii characters that render ok in production but not in development?
Try reading the file as binary:
fsock = open(file_path,"rb")
Try passing the fsock iterator as a parameter to HttpResponse(), rather than to its write() method which I think expects a string.
response = HttpResponse(fsock, mimetype=...)
See http://docs.djangoproject.com/en/dev/ref/request-response/#passing-iterators
Also, I'm not sure you want to call close on your file before returning response. Having played around with this in the shell (I've not tried this in an actual Django view), it seems that the response doesn't access the file until the response itself is read. Trying to read a HttpResponse created using a file that is now closed results in a ValueError: I/O operation on closed file.
So, you might want to leave fsock open, and let the garbage collector deal with it after the response is read.
Try disabling "django.middleware.gzip.GZipMiddleware" from your MIDDLEWARE_CLASSES in settings.py
I had the same problem, and after I looked around the middleware folder, this middleware seemed guilty to me and removing it did the trick for me.