doc/source/basic_use.rst
Basic Use
=========
Document Inheritance
---------------------
First of all, let's see the usual ODM:
.. code:: python
import mongoengine as db
class Address(db.EmbeddedDocument):
"""Address schema."""
street = db.StringField()
city = db.StringField()
state = db.StringField()
class User(db.Document):
"""User data schema."""
name = db.StringField()
email = db.EmailField()
address = db.EmbeddedDocumentListField(Address)
As you can see the code, this code has nothing special. And, when you
serialize the instance into JSON, you will get:
.. code:: json
{
"id": { "$oid": "5700c32a1cbd5856815051ce" },
"name": "Example Man",
"email": "test@example.com",
"address": [
{
"street": "Hello Street",
"city": "Hello City",
"state": "Hello State"
}, {
"street": "World Street",
"city": "World City",
"state": "World State"
}
]
}
And yes, we want to replace :code:`$oid` object with :code:`str` that shows
:code:`5700c32a1cbd5856815051ce`. MongoEngine enables to you do it very easily.
Let's just inherit :code:`mongoengine_goodjson.Document` like this:
.. code:: python
import mongoengine_goodjson as gj
import mongoengine as db
class Address(gj.EmbeddedDocument):
"""Address schema."""
street = db.StringField()
city = db.StringField()
state = db.StringField()
class User(gj.Document):
"""User data schema."""
name = db.StringField()
email = db.EmailField()
address = db.EmbeddedDocumentListField(Address)
Then, running :code:`user.to_json` (:code:`user` is the instance object of User),
you will get the JSON code like this:
.. code:: json
{
"id": "5700c32a1cbd5856815051ce",
"name": "Example Man",
"email": "test@example.com",
"address": [
{
"street": "Hello Street",
"city": "Hello City",
"state": "Hello State"
}, {
"street": "World Street",
"city": "World City",
"state": "World State"
}
]
}
Follow Reference
----------------
Let's see ODM using :code:`ReferenceField`.
.. code:: python
import mongoengine as db
import mongoengine_goodjson as gj
class Book(gj.Document):
"""Book information model."""
name = db.StringField(required=True)
isbn = db.StringField(required=True)
author = db.StringField(required=True)
publisher = db.StringField(required=True)
publish_date = db.DateTimeField(required=True)
class User(gj.Document):
firstname = db.StringField(required=True)
lastname = db.StringField(required=True)
books_bought = db.ListField(db.ReferenceField(Book))
favorite_one = db.ReferenceField(Book)
And here is the JSON data:
.. code:: json
{
"id": "570ee9d1fec55e755db82129",
"firstname": "James",
"lastname": "Smith",
"books_bought": [
"570eea0afec55e755db8212a",
"570eea0bfec55e755db8212b",
"570eea0bfec55e755db8212c"
],
"favorite_one": "570eea0bfec55e755db8212b"
}
This seems to be good deal for :code:`Reference Field`, but sometimes you might
want to generate the Document with Referenced Document like Embedded Document
like this:
.. code:: json
{
"id": "570ee9d1fec55e755db82129",
"firstname": "James",
"lastname": "Smith",
"books_bought": [
{
"id": "570eea0afec55e755db8212a",
"name": "ドグラ・マグラ (上)",
"author": "夢野 久作",
"publisher": "角川文庫",
"publish_date": "1976-10-01",
"isbn": "978-4041366035"
},
{
"id": "570eea0bfec55e755db8212b",
"name": "ドグラ・マグラ (下)",
"author": "夢野 久作",
"publisher": "角川文庫",
"publish_date": "1976-10-01",
"isbn": "978-4041366042"
},
{
"id": "570eea0bfec55e755db8212c",
"name": "The Voynich Manuscript: Full Color Photographic Edition",
"author": "Unknown",
"publisher": "FQ Publishing",
"publish_date": "2015-01-17",
"isbn": "978-1599865553"
}
],
"favorite_one": {
"id": "570eea0bfec55e755db8212b",
"name": "ドグラ・マグラ (下)",
"author": "夢野 久作",
"publisher": "角川文庫",
"publish_date": "1976-10-01",
"isbn": "978-4041366042"
}
}
Of course, you can generate the json document by calling :code:`to_json()`
many times like this:
.. code:: python
def output_references():
user = User.objects(pk=ObjectId("570ee9d1fec55e755db82129")).get()
user_dct = json.loads(user.to_json())
user_dct["books"] = [
json.loads(book.to_json()) for book in user.books_bought
]
user_dct["favorite_one"] = json.loads(user.favorite_one.to_json())
return jsonify(user_dct)
# ...And what if there are references in the referenced document??
However, as you can see, that code is messy and it has a problem that causes
code-bloat. To avoid the problem, this script has a function called
:code:`Follow Reference` since version 0.9. To use it, you can just pass
:code:`follow_reference=True` to :code:`to_json` function like this:
.. code:: python
def output_references():
user = User.objects(pk=ObjectId("570ee9d1fec55e755db82129")).get()
return jsonify(json.loads(user.to_json(follow_reference=True)))
Note that setting :code:`follow_reference=True`, :code:`Document.to_json`
checks the reference recursively until the depth reaches 3rd depth. To change
the maximum recursion depth, you can set the value you want to :code:`max_depth`:
.. code:: python
def output_references():
user = User.objects(pk=ObjectId("570ee9d1fec55e755db82129")).get()
return jsonify(json.loads(user.to_json(follow_reference=True, max_depth=5)))