From 88f54ded71af515be74f671808e26e1326affe8b Mon Sep 17 00:00:00 2001 From: Benjamin Bertrand <benjamin.bertrand@esss.se> Date: Wed, 27 Mar 2019 18:55:04 +0100 Subject: [PATCH] Fix model update in admin interface Following exception is raised when trying to update a network from flask-admin: sqlalchemy.exc.InvalidRequestError: Can't attach instance <User at 0x7f6f0e39ce10>; another instance with key (<class 'app.models.User'>, (1,), None) is already present in this session. 1. If we remove the caching of the load_user method, the problem disappears. 2. When updating a Network, this trigger an inventory update in before_flush which adds a task to the session. This is when the current_user is added to the session and the error raised. So the problem is linked to the user caching and flask-admin. The workaround is to remove the user object added by flask-admin to the session. JIRA INFRA-908 #action In Progress --- app/admin/views.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/admin/views.py b/app/admin/views.py index 5839cab..e954918 100644 --- a/app/admin/views.py +++ b/app/admin/views.py @@ -14,6 +14,7 @@ from flask_admin.contrib import sqla from flask_admin.model.form import converts from flask_login import current_user from ..validators import IPNetwork, ICS_ID_RE +from .. import models # Monkey patch flask-admin Unique validator to disable it @@ -47,6 +48,16 @@ class AdminModelView(sqla.ModelView): def is_accessible(self): return current_user.is_authenticated and current_user.is_admin + def update_model(self, form, model): + # Remove the current user object added by flask-admin from the session + # Adding the current_user object later raises an exception otherwise: + # sqlalchemy.exc.InvalidRequestError: Can't attach instance <User at 0x7f6f0e39ce10>; + # another instance with key (<class 'app.models.User'>, (1,), None) is already present in this session. + for obj in self.session: + if isinstance(obj, models.User) and obj.id == current_user.id: + self.session.expunge(obj) + return super().update_model(form, model) + class UserAdmin(AdminModelView): can_create = False -- GitLab