简体   繁体   中英

Why do I getting 'FileField' object has no attribute 'put'?

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

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM