如何自定义Flask管理查询选择多字段选择?

2024-06-28 20:06:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用flask_admin来允许管理员用户访问数据库,其中显示了一对多关系。当编辑一个条目,我希望下拉菜单只显示符合条件的选项。我认为query_factory可以做到这一点。以下是我现在所拥有的最简单的例子:

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)
    )

{1{1>将显示与cd3}匹配的非活动字段。我被获取当前模型实例ID所困扰。这似乎是一个简单的任务,但我找不到方法来完成它。或者这种方法不可行?在


Tags: idobjdbgetmodelfactoryargscolumn
2条回答

您是对的,模型实例在query_factory中不可用,但实际上并不需要有一个函数传递到该字段。您可以只创建一个查询并将其直接传递给表单。这避免了实例变量,可以在单个方法中完成。在

class ManySideObjView(ModelView):
    def edit_form(self, obj):
        form = super(ManySideObjView, self).edit_form(obj)

        query = self.session.query(OneSideObj).filter(
                    (OneSideObj.active == False) | (OneSideObj.many_side_obj_id == obj.id))

        form.one_side_objs.query = query
        return form

经过几个小时的尝试/错误和谷歌搜索,似乎this几乎就是我想做的。问题归结为这样一个事实:当ModelView启动时,edit_form将不会被调用。因此,我认为没有直接的方法访问正在编辑的模型实例。解决方法是重写edit_form并hijact正在传递模型实例的obj变量。这是为我工作的代码(基于最小化的示例)

class ManySideObjView(ModelView):

    # model instance is passed to edit_form as obj
    def edit_form(self, obj):
        return self._filtered(
            super(ManySideObjView, self).edit_form(obj), obj.id
        )

    # save id in self._instance_id and access it from _get_list
    def _filtered(self, form, id):
        self._instance_id = id
        form.one_side_objs.query_factory = self._get_list
        return form

    # actual query logic
    def _get_list(self):
        id = self._instance_id

        return self.session.query(OneSideObj).filter(
            (OneSideObj.active == False) | (OneSideObj.many_side_obj_id == id)
        )

相关问题 更多 >