I am using flask_admin
to allow admin user to access database, where one-to-many relationship is presented. When editing an entry, I would like the dropdown menu to show only the options that meet the condition. I though query_factory
can do this. The following is minimal example of what I have now:
class OneSideObj(db.Model):
id = db.Column(db.Integer, primary_key=True)
active = db.Column(db.Boolean)
many_side_obj_id = db.Column(
db.Integer,
db.ForeignKey('many_side_obj.id')
)
class ManySideObj(db.Model):
id = db.Column(db.Integer, primary_key=True)
one_side_objs = db.relationship(
'OneSideObj',
backref = 'many_side_obj',
lazy = 'dynamic',
)
def get_manysideobj_id(*args):
##################
# how to get id? #
##################
return id
class ManySideObjView(ModelView):
id = get_manysideobj_id(*some_args) # <--- get current many_side_obj id
form_args = {
'one_side_objs': {
'query_factory': lambda: query_filter(id)
}
}
def query_filter(id):
return OneSideObj.query.filter(
(OneSideObj.many_side_obj_id == id) | (OneSideObj.active == False)
)
The query I would like the field to display is all inactive OneSideObj
, or active ones but with the matching many_side_obj_id
. I am stuck with by getting current model instance ID. It seems to be a simple task but I can't find the way to do it. Or maybe this approach is not doable?
You're right that the model instance isn't available in the
query_factory
, but it's not actually necessary to have a function to pass to that field. You can instead just create a query and pass it directly to the form. This avoids the instance variable and can be done in a single method.After hours of try/error and googling, it seems this is almost what I want to do. The problem boils down to the fact that
edit_form
will not be called whenModelView
initiated. Therefore I believe there is no direct way to access the model instance that is being edited. The work around is to overwriteedit_form
and hijact theobj
variable where the model instance is being passed. This is the code working for me (based on the minimized example)