Search code examples
pythonflaskflask-sqlalchemyflask-loginflask-admin

How to separate views model by id with Flask-admin?


I make a tuition payment app with Flask and using Flask-admin as database management for every school who have registered with my app.

I already make it, but now I'm really not sure how to separate data access between every school account who have registered to manage their own tuition payment.

With Flask-login, I can do it with this code:

@app.route('/school_admin')
@login_required
def school_admin():
    school_data = db.session.query(Student.id, Student.name).filter_by(school_id=current_user.id).all()
    return render_template('school_admin_dashboard.html', school_data=school_data)

But, because Flask-admin generates it table views automatically, I'm really not sure how to do that..?

So far, I have made my ModelView like this:

class SchoolAdminModelView(sqla.ModelView):
    def is_accessible(self):
        if not current_user.is_active or not current_user.is_authenticated:
            return False
        if current_user.has_role('schooladmin'):
            return True

        return False

    def _handle_view(self, name, **kwargs):
        if not self.is_accessible():
            if current_user.is_authenticated:
                # permission denied
                abort(403)
            else:
                # login
                return redirect(url_for('security.login', next=request.url))

class StudentModelView(SchoolAdminModelView):
    pass

admin.add_view(StudentModelView(Student, db.session))

So, how to separate view model by school_id..?

NOTE: my reason why am I using Flask-admin instead of Flask-login for school Admin because of it pretty simple to manage user and superuser roles. And I have using Flask-login for Parent of the student who is the user who consumes this App.


Solution

  • Your code almost works @Joost, but I added a little bit method to it.

    I've found the solution here and modify it a little bit, this is the code how to separate the data access between different school using this way:

    class StudentModelView(sqla.ModelView):
        def get_query(self):
            return Student.query.filter_by(school_id=current_user.id)
    
        def get_count_query(self):
            return self.session.query(func.count('*')).select_from(self.model).filter(
                Student.school_id == current_user.id
            )