0

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

om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
coulix
  • 3,328
  • 6
  • 55
  • 81

4 Answers4

2

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.

brianz
  • 7,268
  • 4
  • 37
  • 44
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()
coulix
  • 3,328
  • 6
  • 55
  • 81
0

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()
Rag Sagar
  • 2,314
  • 1
  • 18
  • 21
0

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.

Hippo
  • 450
  • 8
  • 22