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(开发者_如何学PythonFileField())
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.
精彩评论