From c474ca0f13c0a3d43941fbd99e60b9b708b8fc05 Mon Sep 17 00:00:00 2001 From: Jona Andersen Date: Sun, 22 Apr 2012 13:49:18 +0200 Subject: [PATCH] Allow File-like objects to be stored. No longer demands FileField be an actual instance of file, but instead checks whether object has a 'read' attribute. Fixes read() on GridFSProxy to return an empty string on read failure, or None if file does not exist. --- mongoengine/fields.py | 12 ++++++++---- tests/fields.py | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index 831186d0..a2250f4c 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -875,10 +875,14 @@ class GridFSProxy(object): self.newfile.writelines(lines) def read(self, size=-1): - try: - return self.get().read(size) - except: + gridout = self.get() + if gridout is None: return None + else: + try: + return gridout.read(size) + except: + return "" def delete(self): # Delete file from GridFS, FileField still remains @@ -935,7 +939,7 @@ class FileField(BaseField): def __set__(self, instance, value): key = self.name - if isinstance(value, file) or isinstance(value, str): + if (hasattr(value, 'read') and not isinstance(value, GridFSProxy)) or isinstance(value, str): # using "FileField() = file/string" notation grid_file = instance._data.get(self.name) # If a file already exists, delete it diff --git a/tests/fields.py b/tests/fields.py index 04ef3d90..85c1b385 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -2,6 +2,7 @@ import datetime import os import unittest import uuid +import StringIO from decimal import Decimal @@ -1481,6 +1482,21 @@ class FieldTest(unittest.TestCase): self.assertEquals(result.file.read(), text) self.assertEquals(result.file.content_type, content_type) result.file.delete() # Remove file from GridFS + PutFile.objects.delete() + + # Ensure file-like objects are stored + putfile = PutFile() + putstring = StringIO.StringIO() + putstring.write(text) + putstring.seek(0) + putfile.file.put(putstring, content_type=content_type) + putfile.save() + putfile.validate() + result = PutFile.objects.first() + self.assertTrue(putfile == result) + self.assertEquals(result.file.read(), text) + self.assertEquals(result.file.content_type, content_type) + result.file.delete() streamfile = StreamFile() streamfile.file.new_file(content_type=content_type)