Heinrich Schlegel Heinrich Schlegel - 1 month ago 12
Python Question

Flask-Admin with mongoengine - how to set a “persistent filter” on a view?

I try to use Flask-Admin with Mongoengine and I am totally stuck. I can’t find a solution to implement a “persistent filter”. What I mean by that is, a user should only see and interact with items in a view (list), that are resulting from a custom query in mongoengine.

If I have a model

class User(Document):
name = StringField()
days = DecimalField()
book = StringField()


and I want to show in the first view only books depending on a specific user, I would do a query:

user_peter = User.objects(name=’Peter’)


and if I want to show overdue books for Peter, I would do a query:

overdue_books = User.objects(name=’Peter’, days__gt=28)


how can I implement that in a custom flask-admin-view? What do I have to set in the ModelView?

Class LentBooks(ModelView):
menu_class_name=”Your Books”
#???

Class OverdueBooks(ModelView):
menu_class_name=”Overdue Books”
#???


or do I have to put it here?

Admin.add_view(LentBooks(model=User, #???))


For SQLAlchemy, there are many recipes, but not for mongoengine. Please help!

What I have found, is in flask_admin.contrib.mongoengine.filters

class FilterEqual(BaseMongoEngineFilter):
def apply(self, query, value):
flt = {'%s' % self.column.name: value}
return query.filter(**flt)

def operation(self):
return lazy_gettext('equals')


But how to implement this??

THANK YOU pjcunningham!!

Here is the solution from pjcunningham in a small test-source:

from flask import Flask
import flask_admin as admin
from flask_mongoengine import MongoEngine
from flask_admin.contrib.mongoengine import ModelView

app = Flask(__name__)

app.config['SECRET_KEY'] = '1234567890'
app.config['MONGODB_SETTINGS'] = {'db': 'library'}

db = MongoEngine()
db.init_app(app)

class User(db.Document):
name = db.StringField()
days = db.DecimalField()
book = db.StringField()

class OverdueBooks(ModelView):
def get_query(self):
overdue_books = User.objects(name='Peter', days__gt=28)
return overdue_books

if __name__ == '__main__':

admin = admin.Admin(app, 'Example: Library')

admin.add_view(OverdueBooks(model=User, name='Library'))

app.run(debug=True)


in MongoDB:

{ "_id" : ObjectId("5815f403e198515188860e3c"), "name" : "Jane", "days" : 21, "book" : "Testbook1" }
{ "_id" : ObjectId("5815f416e198515188860e3d"), "name" : "Peter", "days" : 30, "book" : "Testbook2" }


Thank you very much! It works!

Answer

Override get_query in your view. e.g.

class OverdueBooks(ModelView):

    def get_query(self):            
        overdue_books = User.objects(name=’Peter’, days__gt=28)
        return overdue_books