I am trying to unit test my file uploading REST API. I found online some code generating the image with Pillow but it can't be serialized.
This is my code for generating the image :
image = Image.new('RGBA', size=(50, 50), color=(155, 0, 0))
file = BytesIO(image.tobytes())
file.name = 'test.png'
file.seek(0)
Then I try to upload this image fille :
return self.client.post("/api/images/", data=json.dumps({
"image": file,
"item": 1
}), content_type="application/json", format='multipart')
And I get the following error:
<ContentFile: Raw content> is not JSON serializable
How can I transform the Pillow image so it's serializable?
I wouldn't recommend submitting your data as JSON in this case, as it complicates the issue. Just make a POST
request with the parameters and files you want to submit. Django REST Framework will handle it just fine without you needing to serialise it as JSON.
I wrote a test for uploading a file to an API endpoint a while back which looked like this:
def test_post_photo(self):
"""
Test trying to add a photo
"""
# Create an album
album = AlbumFactory(owner=self.user)
# Log user in
self.client.login(username=self.user.username, password='password')
# Create image
image = Image.new('RGB', (100, 100))
tmp_file = tempfile.NamedTemporaryFile(suffix='.jpg')
image.save(tmp_file)
# Send data
with open(tmp_file.name, 'rb') as data:
response = self.client.post(reverse('photo-list'), {'album': 'http://testserver/api/albums/' + album.pk, 'image': data}, format='multipart')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
In this case, I used the tempfile
module to store an image generated using Pillow. The with
syntax used in the example allows you to pass the content of the file in the request body comparatively easily.
Based on this, something like this should work for your use case:
image = Image.new('RGBA', size=(50, 50), color=(155, 0, 0))
file = tempfile.NamedTemporaryFile(suffix='.png')
image.save(file)
with open(file.name, 'rb') as data:
return self.client.post("/api/images/", {"image": data, "item": 1}, format='multipart')
Incidentally, depending on your use case it might be more convenient to accept the image data as a base 64 encoded string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With