hiroaki-yamamoto/mongoengine-goodjson

View on GitHub
doc/source/additional_features.rst

Summary

Maintainability
Test Coverage
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.