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()

2.7.2. Retrieval

So using the FileField is just like using any other field. 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

Note

If you need to read() the content of a file multiple times, you’ll need to “rewind” the file-like object using 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 of the cursor in the file to 0
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

Warning

The 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 contained in marmot instance