Question

Following http://mongoengine.org/docs/v0.4/guide/gridfs.html documentation about mongoengine FileField I did the following:

In my model

files = ListField(FileField())

In my test code

    # Create an entry 
    photo = FileField()
    f  = open('/home/foo/marmot.jpg', 'r')   
    photo.put(f, content_type='image/jpeg')
    entry.files = [photo,]

Trying to follow the doc, however i get an error:

Traceback (most recent call last):
  File "/home/bar/tests.py", line 76, in test_MongoDGACLogook_creation
    photo.put(f, content_type='image/jpeg')
AttributeError: 'FileField' object has no attribute 'put'

Am I missing something obvious ?

Thanks

Was it helpful?

Solution 2

    f = mongoengine.fields.GridFSProxy()
    to_read = open('/home/.../marmot.jpg', 'r')   
    f.put(to_read, filename=os.path.basename(to_read.name))
    to_read.close()

OTHER TIPS

This isn't obvious at all IMO, but if you look at the Mongoengine code you'll see that the put method is defined in the GridFSProxy class, which is accessed via a descriptor in FileField (the __get__ and __set__ methods).

Looking at the code and the examples in the docs, it appears the only way to access or use a FileField is through the descriptor....so, collection.file_field.

Given all this, I don't think it's possible to have a list of file fields using the Mongoengine API as it exists now.

If you are uploading multiples files and trying to save it a ListField(FileField())

<input type='file' name='myfiles' multiple="">

files = []
for f in request.FILES.getlist('myfiles'):
    mf = mongoengine.fields.GridFSProxy()
    mf.put(f, filename=f.name)
    files.append(mf)
entry.files = files
entry.save()

I had exactly the same problem. As suggested by @KoppeKTop on GitHub in this post, I finally extended my model (Pet) using an EmbeddedDocument like this:

class OneImage(mongoengine.EmbeddedDocument):
    element = ImageField()

class Pet(mongoengine.Document):
    photos = EmbeddedDocumentListField(OneImage)
    # ...more fields... #

I can then add a new image using

    i = OneImage()
    i.element.put(form.photo.data.stream)
    entry.photos.append(i)
    entry.save()

This may not always be the best option, but personally I prefer it because I can work with models as usual without having to work with proxies. And I can also save other photo metadata in the future, if I need to.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top