如何在Flask Admin中的* -to-Many关系模型视图中进行自定义查询?

时间:2015-06-08 15:54:20

标签: python flask sqlalchemy flask-admin

我从Flask Admin开始,我遇到了一个无法解决的问题,即使经过几个小时的寻找方法在文档中解决它。

我更改了实体的名称以便更加了解,但问题完全相同。

我与实体用户和实体之间存在多对多关系(我的问题与一对多关系相同)技能:用户可以拥有多种技能,不同的用户可以拥有相同的技能。

在实体技能的创建(或版本)页面上,有一个字段用于"用户"关系。

我有超过10万用户,当我点击该字段时,它很慢(由于Javascript搜索脚本)。

为了加快速度,我只想搜索“活跃的”字样。用户(活动是我的SQL数据库中的布尔字段),因为实际上有一些活跃的用户,我永远不会为非活动用户添加技能。

我该怎么做?

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.admin.contrib.sqla import ModelView
from flask.ext.admin import Admin

app = Flask(__name__)
db = SQLAlchemy(app)
admin = Admin(app)

association_table = db.Table(
    'user_skill',
    db.Column('user_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
    db.Column('skill_id', db.Integer, db.ForeignKey('skill.id'), primary_key=True)
)

class Skill(db.Model):
    name = db.Column(db.String(30), nullable=True)

class User(db.Model):
    username = db.Column(db.String(30), nullable=True)
    skills   = db.relationship(
        'Skill',
        secondary=association_table,
        backref='users'
    )

class SkillView(ModelView):

    # Something like that
    form_relationship_query = {'users': lambda query: query.filter_by(active=True).all()}

admin.add_view(SkillView(Skill, db.session))

4 个答案:

答案 0 :(得分:3)

我想你错过了Flask-Admin default filters。所以在你的情况下,它应该是:

class SkillView(ModelView):

    def get_query(self):
       return self.session.query(self.model).filter(self.model.active == True)

    def get_count_query(self):
        return self.get_query().count()

答案 1 :(得分:3)

我找到了解决方案:

class SkillView(ModelView):

    form_ajax_refs = {
        'users': {
            'fields': (User.username,)
        }
    }

这不仅显示活动用户,但它解决了我的初始问题,即用户字段性能。现在,我们必须在User字段中输入至少一个字母才能启动JS请求,并且html永远不会使窗口冻结。

答案 2 :(得分:1)

感谢您的回答。

首先,我想你想说:

1st Table 'sensors'
-------------------------------------------------------------
id    sensorId      location    city    country     userId     
-------------------------------------------------------------

2nd Table sensordata
-------------------------------
id    sensorId     dataValues  
-------------------------------

否则,过滤器将应用于实体Skill的“active”列,该列不存在..

该解决方案正在运行,我已经尝试过,但它与我正在寻找的有点不同:实际上,通过更改这些默认过滤器,我只会在用户视图中看到活动用户。 我想要的是保持ALTER TABLE `sensordata` s ADD `location` VARCHAR( 200 ) NOT NULL DEFAULT (SELECT location from sensors s WHERE s.sensorId = d.sensorId) AFTER `dataValues` 中的所有用户(活动和非活动),但只能在class UserView(ModelView): def get_query(self): return self.session.query(self.model).filter(self.model.active == True) def get_count_query(self): return self.get_query().count() 的用户字段中选择活动用户。

编辑:验证后,似乎使用此解决方案甚至无法解决我的问题:不仅我在UserView中看到只有活动用户,而且我看到所有用户(活动和在UserView的字段中,这使得JS非常慢。

答案 3 :(得分:1)

您可以使用如下所示的ajax加载器来改进它:

form_ajax_refs = {
    'users': QueryAjaxModelLoader(
        'users',
        db.session,
        User,
        fields=['username'],
        page_size=10,
        filters=["active=True"]
    ),

}