MongoEngine/mongoengine

Ability to create computed fields?

jacquelinegarrahan opened this issue · 1 comments

I'm wondering if there are any existing examples of using custom fields for templating based on the values of other fields, for example:

class UniqueResultField(StringField):
    """Provides unique hashing on index string"
  
    def __init__(self, **kwargs):
        ...

    def to_python(self, value):
        ...

class ResultDocument(Document):
    flow_id = StringField(max_length=200, required=True)
    inputs = DictField(required=True)
    outputs = DictField(required=True)
    date_modified = DateTimeField(default=datetime.utcnow)

    # Used for identifying index
    unique_result_hash = UniqueResultField() # will use results of 

I'd like to have the unique hash calculated before saving in order to perform existence checks. I'm aware that the hashing and existence replicates the indexing, but am unfortunately working with a framework that requires string based target references for task results.

For anyone trying to implement something similar, I was able to get my desired functionality using the post_init signal like so:

class ResultDocument(Document):
    flow_id = StringField(max_length=200, required=True)
    inputs = DictField(required=True)
    outputs = DictField(required=True)
    date_modified = DateTimeField(default=datetime.utcnow)

    # Used for identifying index
    unique_result_hash = StringField(default=None)

    @classmethod()
     def post_init(cls, sender, document, **kwargs):
        document.unique_result_hash = fingerprint_dict(
                {
                    "inputs": document.inputs,
                    "outputs": document.outputs,
                    "flow_id": document.flow_id
                }
            )

signals.post_init.connect(ResultDocument.post_init, sender=ResultDocument)

Note: If ResultDocument was an abstract class, you'd have to list sender as the child class in order for the signals to function properly.