doc/source/additional_features.rst
Addtional Features
==================
FollowReferenceField
--------------------
This script also provides a field that supports serialization of the reference
with :code:`follow_reference=True`. Unlike :code:`ReferenceField`, this field
supports deserialization and automatic-save.
To use this field, you can just simply declare the field as usual.
For example, like this:
.. code:: python
import mongoengine as db
import mongoengine_goodjson as gj
class User(gj.Document):
"""User info."""
name = db.StringField()
email = db.EmailField()
class DetailedProfile(gj.Document):
"""Detail profile of the user."""
# FollowReferenceField without auto-save
user = gj.FollowReferenceField(User)
yob = db.DateTimeField()
# FollowReferenceField with auto-save
partner = gj.FollowReferenceField(User, autosave=True)
Exclude fields from JSON serialization/deserialization
------------------------------------------------------
Sometimes you might want to exclude fields from JSON serialization, but to do
so, you might need to decode JSON-serialized string, pop the key, then, serialize
the dict object again. Since 0.11, metadata :code:`exclude_to_json`,
:code:`exclude_from_json`, and code:`exclude_json` are available and they
exclude field on the following specific actions:
- Setting Truthy value to :code:`exclude_to_json`, the corresponding field is
omitted from JSON encoding. Note that this excludes fields JSON encoding only.
- Setting Truthy value to :code:`exclude_from_json`, the corresponding field is
omitted from JSON decoding. Note that this excludes fields JSON decoding only.
- Setting Truhy value to :code:`exclude_json`, the corresponding field is
omitted from JSON encoding and decoding.
Example
~~~~~~~
To use the exclusion, you can just put exclude metadata like this:
.. code:: python
import mongoengine_goodjson as gj
import mongoengine as db
class ExclusionModel(gj.Document):
"""Example Model."""
to_json_exclude = db.StringField(exclude_to_json=True)
from_json_exclude = db.IntField(exclude_from_json=True)
json_exclude = db.StringField(exclude_json=True)
required = db.StringField(required=True)
def get_json_obj(*q, **query):
model = Exclude.objects(*q, **query).get()
# Just simply call to_json :)
return model.to_json()
def get_json_list(*q, **query):
# You can also get JSON serialized text from QuerySet.
return Exclude.objects(*q, **query).to_json()
# Decoding is also simple.
def get_obj_from_json(json_text):
return Exclude.from_json(json_text)
def get_list_from_json(json_text):
return Exclude.objects.from_json(json_text)
Reference Limit
---------------
Since version 1.0.0, the method to limit recursive depth is implemented.
By default, :code:`to_json` serializes the document until the cursor reaches
3rd level. To change the maximum depth level, change :code:`max_depth` kwargs.
As of 1.1.0, callable function can be set to :code:`max_depth`, and
:code:`to_json` calls max_depth with the document that the field holds, and
current depth level. If the function that is associated with :code:`max_depth`
returns truthy values, the serialization will be stop.
Note that when you use callable :code:`max_depth` of
:code:`FollowReferenceField`, the border of the document i.e. the document
that :code:`max_depth` returned truthy value, will **NOT** be serialized while
:code:`to_json()` does. It just be "id" of the model.
Code Example
~~~~~~~~~~~~
Here is the code example of Limit Recursion:
.. code:: python
import mongoengine as db
import mongoengine_goodjson as gj
class User(gj.Document):
"""User info."""
name = db.StringField()
email = db.EmailField()
# i.e. You can access everyone in the world by Six Degrees of Separation
friends = db.ListField(gj.FollowReferenceField("self", max_depth=6))
# If the name of the user is Alice, Mary, or Bob, it will refer more depth.
not_friend = gj.FollowReferenceField(
"self", max_depth=lambda doc, cur_depth: doc.name not in [
"Alice", "Mary", "Bob"
]
)
class DetailedProfile(gj.Document):
"""Detail profile of the user."""
user = gj.FollowReferenceField(User)
yob = db.DateTimeField()
To disable the limit, put negative number to :code:`max_depth`, however you
should make sure that the model has neither circuit nor self-reference.