Testing Image upload with Django and Webtest - django

Does anyone know how I can test the image upload with using WebTest. My current code is:
form['avatar'] =('avatar', os.path.join(settings.PROJECT_PATH, 'static', 'img', 'avatar.png'))
res = form.submit()
In the response I get the following error "Upload a valid image. The file you uploaded was either not an image or a corrupted image.".
Any help will be appreciated.

Power was right. Unfortunately(or not) I found his answer after I spend half an hour debugging the webtest. Here is a bit more information.
Trying to pass only the path to the files brings you the following exception:
webtest/app.py", line 1028, in _get_file_info
ValueError: upload_files need to be a list of tuples of (fieldname,
filename, filecontent) or (fieldname, filename); you gave: ...
The problem is that is doesn't told you that it automatically will append the field name to the tuple send and making 3 item tuple into 4 item one. The final solutions was:
avatar = ('avatar',
file(os.path.join(settings.PROJECT_PATH, '....', 'avatar.png')).read())
Too bad that there is not decent example but I hope this will help anyone else too )

Nowadays selected answer didn't help me.
But I found the way to provide expected files in the .submit() method args
form.submit(upload_files=[('avatar', '/../file_path.png')])

With Python 3:
form["avatar"] = ("avatar.png", open(os.path.join(settings.PROJECT_PATH, '....', 'avatar.png', "rb").read())

Related

How to properly save instance of FileField in Django

Im hoping someone can tell me what I am doing wrong and point me in the right direction.
So, I am creating an array of Model objects and then doing a bulk_create at the end to save them to the database. The one thing I am having an issue with is after I added the the FileField I cannot exactly how I need to associate data with that field. The files don't end up in the upload_to folder set nor do they end up being associated with the record itself. Id also add that I am using PyPDf2 to create the PDF files before trying to associate them to an instance of my model.
So to give you an idea on what I am trying to do. I am running this code to create the PDFs initially.
if pdf_file_name is not None:
num_pages_current_doc = page['pageRange'][-1]
input_pdf = PdfFileReader(open(pdf_file_name, 'rb'))
output_pdf = PdfFileWriter()
for _ in range(num_pages_current_doc):
output_pdf.addPage(input_pdf.getPage(page_counter))
page_counter += 1
with open(str(uuid.uuid4())+'.pdf', 'wb') as output:
output_pdf.write(output)
logging.info(f'Wrote filename: { output.name }')
The saved file I then want to associated with a model instance below this, the code looks something like this:
document = document(
location=location,
Field2=Field2, etc etc .....
pdf = ???
Im unsure how to set the field for that pdf part, Ive tried using the File() method on it. Tried putting just output.name for the field, Im not sure how to go about making this work.
Could anyone give me some insight?
Thanks!
See the FieldFile.save(name, content, save=True) method in django docs. https://docs.djangoproject.com/en/3.2/ref/models/fields/#filefield-and-fieldfile

read text file content with python at zapier

I have problems getting the content of a txt-file into a Zapier
object using https://zapier.com/help/code-python/. Here is the code I am
using:
with open('file', 'r') as content_file:
content = content_file.read()
I'd be glad if you could help me with this. Thanks for that!
David here, from the Zapier Platform team.
Your code as written doesn't work because the first argument for the open function is the filepath. There's no file at the path 'file', so you'll get an error. You access the input via the input_data dictionary.
That being said, the input is a url, not a file. You need to use urllib to read that url. I found the answer here.
I've got a working copy of the code like so:
import urllib2 # the lib that handles the url stuff
result = []
data = urllib2.urlopen(input_data['file'])
for line in data: # file lines are iterable
result.append(line) # keep each line, or parse, etc.
return {'lines': result}
The key takeaway is that you need to return a dictionary from the function, so make sure you somehow squish your file into one.
​Let me know if you've got any other questions!
#xavid, did you test this in Zapier?
It fails miserably beacuse urllib2 doesn't exist in the zapier python environment.

YouTube API: youtube.search().list won't order by date

I'm trying to get a list of all recent Youtube uploads using Python and API v3.0. I'm using youtube.search().list, but the results were all uploaded at seemingly random times in the last few years, and are not ordered by date. I've attached a sample of my code.
def getSearchResults():
""" Perform an empty search """
search_results = youtube.search().list(
part="snippet",
order="date",
maxResults=50,
type="video",
q=""
).execute()
return search_results
def getVideoDetails(video):
""" Get details of search results """
video_id = video["id"]["videoId"]
video_title = video["snippet"]["title"]
video_date = video["snippet"]["publishedAt"]
return video_id, video_title, video_date
search_results = getSearchResults()
for result in search_results["items"]:
print getVideoDetails(result)
Any help is greatly appreciated!
EDIT: After retrying a few times, sometimes I will get the correct output (the most recently uploaded videos sorted by upload date) and sometimes I won't (resulting in videos from seemingly random times). I have no idea what the result depends on, but at certain times of the day it works, at others it doesn't, so the issue seems to be with the API and not my code.
EDIT 2: Further evidence that the API is at fault: ordering by date or title on the API Reference's Try It section for youtube.search().list is wack, too.
UPDATE: Google have acknowledged the issue and seem to have fixed it.

Server side problems saving a file uploaded using requests.POST

Below is my python snippet code to upload a file on certain server:
import requests
url = "http://<my_url>"
files = {'file':open("<file to be uploaded>", "rb"), "name":"<name of the file>"}
r = requests.post(url, files=files)
Status code is 200, so it's OK.
My question is, on the server side, how do I save this file?
I can access 'name' on the dict thru this:
request.POST.get('name')
I can access the 'file' as well but I can't save it. I am trying this:
ufile = request.POST.get('file')
dest = open("<file on the server side>", "wb+")
for chunk in ufile.chunks():
dest.write(chunk)
dest.close()
But this is not working and it throws this exception:
unicode object has no attribute 'chunks'
I also tried:
ufile.save(<"filepath on the server side">)
But I encountered the same exception.
Hoping for any feedback! Thanks in advance!
Files are not in request.POST, they are in request.FILES.
But you probably want to read the file uploads documentation.
Try the following instead of writing chunk by chunk:
dest.write(ufile)
The ufile object is a string, not a file handle.
Had the same issue..
You should delete "Content-type" from request header, and your file will appear in request.FILES, then you can work with <TemporaryUploadedFile>
I think this answer not relevant for #jaysonpryde, but maybe will help someone else.. :)

How to submit image uploads in Django tests?

The Django docs (http://docs.djangoproject.com/en/dev/topics/testing/#django.test.client.Client.post) say to do this:
>>> c = Client()
>>> f = open('wishlist.doc')
>>> c.post('/customers/wishes/', {'name': 'fred', 'attachment': f})
>>> f.close()
But when I do that the field has the error message "The submitted file is empty." That smells like a PIL issue but the form works fine on the actual site.
Reading the file and sending that instead of just a handle doesn't work either and behaves the same as passing an empty string.
OK I figured it out. I was using the same dummy image for multiple fields and Django doesn't reset the pointer after validating the first field.
Also the example in the docs doesn't show that images need to be opened in binary mode as well.
I think open expects a file path relative to where it’s being called from.
I’m not sure where that would be when a test is being run, but maybe try with an absolute path and see if it works?