Search code examples
pythonmongodbmongoengineflask-admin

Load flask admin ListView even when a reference field is missing/deleted


I have made two API's with Flask Admin and mongoengine, This is how my document is in the first API.

class Score(db.Document):
    score = StringField(required=True)
    section= ReferenceField(ScoreDocument,db_field='score',required=True)
    name = StringField(required=True)
    meta = {
        'collection': 'score',
    }

To get Score data in the second API, this is what I do

class ScoreDocument(db.Document):
            score = StringField(required=True)
            meta = {
                'collection': 'score',
                 strict = False
            }


class DisplayType(db.Document):
        displayType= StringField(required=True)
        section= ReferenceField(ScoreDocument,db_field='section',required=True)
        meta = {
            'collection': 'score',
        }

As both these APIs fetch data from the same database, If a value were removed from the 'section' field in the referenced document, it would result in the following error, causing the Flask Admin list view to not load.

mongoengine.errors.DoesNotExist: Trying to dereference unknown document DBRef('section', ObjectId('62286f65088c4f1d723574c6'))

Using reverse_delete_rule=mongoengine.NULLIFY in the reference field would have been a straightforward solution. However, it does not work in this scenario because of the documents association with unique mongoengine instances, as they belong to two different APIs.

Is there someway to override the listview in flaskadmin so it loads up even when the reference field has a missing/deleted value.


Solution

  • If someone is looking for an answer

    class UpgradedModelView(ModelView):
        # This function belongs to the ModelView
        def _get_field_value(self, model, name):
            try:
                return rec_getattr(model, name)
            except DoesNotExist:
                return "<invalid>"
    
    
    class ScoreView(UpgradedModelView):
        sponsor_column_initial_value = None
        column_display_pk = True
        column_searchable_list = ['name']
        column_filters = ['score']
    

    I created a class called UpgradedModelView which inherits from ModelView, the view that has a reference field inherits from this class, each time you load a view in Flask admin the _get_field_value function is called, now to get around the problem if I get a reference field that does not exist anymore,

    except DoesNotExist:
       return "<invalid>"
    

    I catch the error and return "invalid" string. I can then later either manually delete the records or write a script for the same

    enter image description here