Search code examples
eve

add a calculated field to eve schema


is there a way to bring an own calculated field into the schema which can be filled with an value calculated in a before_output event from flask, or something?

schema = {
    # Schema definition, based on Cerberus grammar. Check the Cerberus project
    # (https://github.com/nicolaiarocci/cerberus) for details.
    'firstname': {
        'type': 'string',
        'minlength': 1,
        'maxlength': 10,
    },
    'lastname': {
        'type': 'string',
        'minlength': 1,
        'maxlength': 15,
        'required': True,
        # talk about hard constraints! For the purpose of the demo
        # 'lastname' is an API entry-point, so we need it to be unique.
        'unique': True,
    },
    # 'role' is a list, and can only contain values from 'allowed'.
    'role': {
        'type': 'list',
        'allowed': ["author", "contributor", "copy"],
    },
    # An embedded 'strongly-typed' dictionary.
    'location': {
        'type': 'dict',
        'schema': {
            'address': {'type': 'string'},
            'city': {'type': 'string'}
        },
    },
    'born': {
        'type': 'datetime',
    },
    'calculated_field': {
        'type': 'string',
    }
}

and the calculated_field is filled using an own mongodb query statement.


Solution

    1. Update your settings so that your field is flagged as read-only: 'calculated_field': {'readonly': True}. This will prevent clients from accidentally writing into the field. Setting it as a string type is probably not necessary;
    2. Add a callback function to your launch script. This will process outbound documents, injecting calculated values in your read-only field;
    3. Attach your callback to the application's on_fetched event.
    4. Launch the application.

    So your script might look something like:

    from eve import Eve
    
    # the callback function
    def add_calculated_field_value(resource, response):                                          
        for doc in response['_items']:                                                    
            doc['calculated_field'] = 'hello I am a calculated field'
    
    # instantiate the app and attach the callback function to the right event
    app = Eve()
    app.on_fetched_resource += add_calculated_field_value
    
    if __name__ == '__main__':
        app.run()