File: gridfs.rst

package info (click to toggle)
python-mongoengine 0.29.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 908 kB
  • sloc: python: 7,194; makefile: 57; sh: 17
file content (89 lines) | stat: -rw-r--r-- 3,174 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
======
GridFS
======

Writing
-------

GridFS support comes in the form of the :class:`~mongoengine.fields.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 <https://pymongo.readthedocs.io/en/stable/examples/gridfs.html#gridfs-example>`_
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()

Retrieval
---------

So using the :class:`~mongoengine.fields.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

Streaming
---------

Streaming data into a :class:`~mongoengine.fields.FileField` is achieved in a
slightly different manner.  First, a new file must be created by calling the
:func:`new_file` method. Data can then be written using :func:`write`::

    marmot.photo.new_file()
    marmot.photo.write('some_image_data')
    marmot.photo.write('some_more_image_data')
    marmot.photo.close()

    marmot.save()

Deletion
--------

Deleting stored files is achieved with the :func:`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.


Replacing files
---------------

Files can be replaced with the :func:`replace` method. This works just like
the :func:`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