2.7. GridFS
2.7.1. Writing
GridFS support comes in the form of the FileField field object. This field
acts as a file-like object and provides a couple of different ways of inserting and
retrieving data. Arbitrary metadata such as content type can also be stored alongside the
files. The object returned when accessing a FileField is a proxy to
Pymongo's GridFS.
In the following example, a document is created to store details about animals, including
a photo:
class Animal(Document):
genus = StringField()
family = StringField()
photo = FileField()
marmot = Animal(genus='Marmota', family='Sciuridae')
with open('marmot.jpg', 'rb') as fd:
marmot.photo.put(fd, content_type='image/jpeg')
marmot.save()
So using the FileField is just like using any other field.
2.7.2. Retrieval
The file can also be retrieved just as easily:
marmot = Animal.objects(genus='Marmota').first()
photo = marmot.photo.read()
content_type = marmot.photo.content_type
seek:
marmot = Animal.objects(genus='Marmota').first()
content1 = marmot.photo.read()
assert content1 != ''
content2 = marmot.photo.read() # will be empty
assert content2 == ''
marmot.photo.seek(0) # rewind the file by setting the current position to the start
content3 = marmot.photo.read()
assert content3 == content1
2.7.3. Streaming
Streaming data into a FileField is achieved in a slightly different manner.
First, a new file must be created by calling the new_file() method. Data can
then be written using write():
marmot.photo.new_file()
marmot.photo.write('some_image_data')
marmot.photo.write('some_more_image_data')
marmot.photo.close()
marmot.save()
2.7.4. Deletion
Deleting stored files is achieved with the delete() method:
marmot.photo.delete() # Deletes the GridFS document
marmot.save() # Saves the GridFS reference (being None) contained in the marmot instance
FileField in a Document actually only stores the ID of a file in a
separate GridFS collection. This means that deleting a document with a defined
FileField does not actually delete the file. You must be careful to delete
any files in a Document as above before deleting the Document itself.
2.7.5. Replacing files
Files can be replaced with the replace() method. This works just like the
put() method so even metadata can (and should) be replaced:
another_marmot = open('another_marmot.png', 'rb')
marmot.photo.replace(another_marmot, content_type='image/png') # Replaces the GridFS document
marmot.save() # Replaces the GridFS reference