Flask 会议 app.config['SECRET_KEY']='123456790' #创建内存数据库 app.config['DATABASE_FILE']='sample_db.sqlite' app.config['SQLALCHEMY\u DATABASE\u URI']='sqlite://'+app.config['DATABASE\u FILE'] app.config['SQLALCHEMY_ECHO']=True db.init_应用程序(应用程序) admin=admin(应用程序,模板=“bootstrap3”) admin.add_视图(UserAdmin(User,db.session)) #烧瓶视图 @应用程序路径(“/”) def index(): 返回“” @第一次请求前的应用程序 def build_sample_db(): db.drop_all() db.create_all() user_obj1=用户(first_name=“Paul”,last_name=“Brown”,username=“pbrown”,email=”paul@gmail.com") user_obj2=user(first_name=“Luke”,last_name=“Brown”,username=“lbrown”,email=”luke@gmail.com") user_obj3=用户(first_name=“Serge”,last_name=“Koval”,username=“skoval”,email=”serge@gmail.com") db.session.add_all([user_obj1,user_obj2,user_obj3]) db.session.commit() 返回应用程序 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': app=create_app() 运行(端口=5000,调试=True)

Flask 会议 app.config['SECRET_KEY']='123456790' #创建内存数据库 app.config['DATABASE_FILE']='sample_db.sqlite' app.config['SQLALCHEMY\u DATABASE\u URI']='sqlite://'+app.config['DATABASE\u FILE'] app.config['SQLALCHEMY_ECHO']=True db.init_应用程序(应用程序) admin=admin(应用程序,模板=“bootstrap3”) admin.add_视图(UserAdmin(User,db.session)) #烧瓶视图 @应用程序路径(“/”) def index(): 返回“” @第一次请求前的应用程序 def build_sample_db(): db.drop_all() db.create_all() user_obj1=用户(first_name=“Paul”,last_name=“Brown”,username=“pbrown”,email=”paul@gmail.com") user_obj2=user(first_name=“Luke”,last_name=“Brown”,username=“lbrown”,email=”luke@gmail.com") user_obj3=用户(first_name=“Serge”,last_name=“Koval”,username=“skoval”,email=”serge@gmail.com") db.session.add_all([user_obj1,user_obj2,user_obj3]) db.session.commit() 返回应用程序 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': app=create_app() 运行(端口=5000,调试=True),flask,flask-sqlalchemy,flask-admin,Flask,Flask Sqlalchemy,Flask Admin,Flask应用程序工厂的版本(创建应用程序,当前应用程序,应用程序上下文等等):) 您可以使用flaskhas\u request\u context函数 检查返回筛选器选项元组的函数中是否存在请求上下文。 当选项来自DB,但此时请求上下文不存在时,它会有所帮助 def _get_options_for_filter() if not has_request_context(): return () return tuple([(o.id, o.title) fo

Flask应用程序工厂的版本(
创建应用程序
当前应用程序
应用程序上下文
等等):)


您可以使用flask
has\u request\u context
函数 检查返回筛选器选项元组的函数中是否存在请求上下文。 当选项来自DB,但此时请求上下文不存在时,它会有所帮助

def _get_options_for_filter()
    if not has_request_context():
        return ()
    return tuple([(o.id, o.title) for o in Options.query.all()])

嗯,这个函数在应用程序启动时被调用。即使重新加载页面也不会触发再次加载:-(@Sebi-您需要更新过滤器缓存-我已经更新了我的answer@pjcunningham即使与app.app_context()一起使用,过滤器也不会刷新,只有手动重新加载应用程序。有什么想法吗?:)@sortas-添加了一个文件演示。@PjRunningham谢谢,尝试了同样的方法,但它似乎不适用于应用程序工厂(
create\u app()
等等)。因此,现在我试图覆盖
\u refresh\u filters\u cache
方法,以便在每次重新加载页面时从db查询选项。我认为最好只覆盖
get\u filters
,而不是重复基本代码。另外,调用
index\u view
时,应用程序上下文不是已经建立了吗?我已经根据你的代码在我的答案中添加了一个应用程序工厂示例。非常感谢!管理员中的动态筛选器以某种方式锁定了数据库表,从而阻止了我的alembic迁移,原因是启动时刷新了筛选器缓存。测试请求上下文解决了我的问题
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

from flask_admin.contrib import sqla
from flask_admin import Admin, expose

# required for creating custom filters
from flask_admin.contrib.sqla.filters import BaseSQLAFilter, FilterEqual

app = Flask(__name__)

# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'

# Create in-memory database
app.config['DATABASE_FILE'] = 'sample_db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)


# Flask views
@app.route('/')
def index():
    return '<a href="/admin/">Click me to get to Admin!</a>'


# Create model
class User(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(100))
    last_name = db.Column(db.String(100))
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)

    # Required for admin interface. For python 3 please use __str__ instead.
    def __unicode__(self):
        return self.username


# Create custom filter class
class FilterLastNameBrown(BaseSQLAFilter):
    def apply(self, query, value, alias=None):
        if value == '1':
            return query.filter(self.column == "Brown")
        else:
            return query.filter(self.column != "Brown")

    def operation(self):
        return 'is Brown'


def get_options():
    return [('1', 'Yes'), ('0', 'No')]


def get_all_last_names():
    unique_last_names = User.query.with_entities(User.last_name.distinct().label("last_name")).order_by(
        User.last_name.asc()).all()
    return [(user.last_name, user.last_name) for user in unique_last_names]


# Add custom filter and standard FilterEqual to ModelView
class UserAdmin(sqla.ModelView):

    column_filters = [
        FilterEqual(column=User.last_name, name='Last Name', options=get_all_last_names),
        FilterLastNameBrown(column=User.last_name, name='Last Name', options=(('1', 'Yes'), ('0', 'No')))
    ]

    # This is probably NOT the correct way to refresh the filters cache
    @expose('/')
    def index_view(self):
        self._refresh_filters_cache()
        return super(UserAdmin, self).index_view()


admin = Admin(app, template_mode="bootstrap3")
admin.add_view(UserAdmin(User, db.session))


def build_sample_db():
    db.drop_all()
    db.create_all()
    user_obj1 = User(first_name="Paul", last_name="Brown", username="pbrown", email="paul@gmail.com")
    user_obj2 = User(first_name="Luke", last_name="Brown", username="lbrown", email="luke@gmail.com")
    user_obj3 = User(first_name="Serge", last_name="Koval", username="skoval", email="serge@gmail.com")

    db.session.add_all([user_obj1, user_obj2, user_obj3])
    db.session.commit()


if __name__ == '__main__':
    build_sample_db()
    app.run(port=5000, debug=True)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

from flask_admin.contrib import sqla
from flask_admin import Admin, expose

# required for creating custom filters
from flask_admin.contrib.sqla.filters import BaseSQLAFilter, FilterEqual

db = SQLAlchemy()


class User(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(100))
    last_name = db.Column(db.String(100))
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)

    # Required for admin interface. For python 3 please use __str__ instead.
    def __unicode__(self):
        return self.username


# Create custom filter class
class FilterLastNameBrown(BaseSQLAFilter):
    def apply(self, query, value, alias=None):
        if value == '1':
            return query.filter(self.column == "Brown")
        else:
            return query.filter(self.column != "Brown")

    def operation(self):
        return 'is Brown'


def get_options():
    return [('1', 'Yes'), ('0', 'No')]


def get_all_last_names():
    unique_last_names = User.query.with_entities(User.last_name.distinct().label("last_name")).order_by(
        User.last_name.asc()).all()
    return [(user.last_name, user.last_name) for user in unique_last_names]


# Add custom filter and dynamic FilterEqual to ModelView
class UserAdmin(sqla.ModelView):

    column_filters = [
        FilterLastNameBrown(column=User.last_name, name='Last Name', options=(('1', 'Yes'), ('0', 'No')))
    ]

    def get_filters(self):
        _dynamic_filters = getattr(self, 'dynamic_filters', None)
        if _dynamic_filters:
            return (super(UserAdmin, self).get_filters() or []) + _dynamic_filters
        else:
            return super(UserAdmin, self).get_filters()

    @expose('/')
    def index_view(self):
        self.dynamic_filters = []
        self.dynamic_filters.extend([
            FilterEqual(column=User.last_name, name='Last Name', options=get_all_last_names),
            # Add further dynamic filters here
        ])
        self._refresh_filters_cache()
        return super(UserAdmin, self).index_view()


def create_app():

    app = Flask(__name__)

    # Create dummy secrey key so we can use sessions
    app.config['SECRET_KEY'] = '123456790'

    # Create in-memory database
    app.config['DATABASE_FILE'] = 'sample_db.sqlite'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
    app.config['SQLALCHEMY_ECHO'] = True
    db.init_app(app)
    admin = Admin(app, template_mode="bootstrap3")
    admin.add_view(UserAdmin(User, db.session))

    # Flask views
    @app.route('/')
    def index():
        return '<a href="/admin/">Click me to get to Admin!</a>'

    @app.before_first_request
    def build_sample_db():
        db.drop_all()
        db.create_all()
        user_obj1 = User(first_name="Paul", last_name="Brown", username="pbrown", email="paul@gmail.com")
        user_obj2 = User(first_name="Luke", last_name="Brown", username="lbrown", email="luke@gmail.com")
        user_obj3 = User(first_name="Serge", last_name="Koval", username="skoval", email="serge@gmail.com")

        db.session.add_all([user_obj1, user_obj2, user_obj3])
        db.session.commit()

    return app


if __name__ == '__main__':
    app = create_app()
    app.run(port=5000, debug=True)
# Dynamic filter update method for Flask app factories
# Override version of base _refresh_filters_cache method
def update_dynamic_filters(self, dynamic_filters):

    # Get base filters
    self._filters = self.get_filters()

    # Add dynamic filters (to the beginning)
    for dft in dynamic_filters:
        self._filters.insert(0, dft)

    if self._filters:
        self._filter_groups = OrderedDict()
        self._filter_args = {}

        for i, flt in enumerate(self._filters):
            key = as_unicode(flt.name)
            if key not in self._filter_groups:
                self._filter_groups[key] = FilterGroup(flt.name)
            self._filter_groups[key].append(
                {
                    'index': i,
                    'arg': self.get_filter_arg(i, flt),
                    'operation': flt.operation(),
                    'options': flt.get_options(self) or None,
                    'type': flt.data_type,
                }
            )
            self._filter_args[self.get_filter_arg(i, flt)] = (i, flt)
    else:
        self._filter_groups = None
        self._filter_args = None

# Update view every page reload (thanks to the @pjcunningham)
@expose('/')
def index_view(self):
    dynamic_filters = []
    # Working with db in app_context
    with app.app_context():
        # Adding dynamic filters
        dynamic_filters.append(
            FilterInList(
                column=Record.record_condition,
                name='Condition',
                options=[
                    (x[0], x[0])
                    for x in db.session.query(Record.record_condition)
                    .distinct()
                    .all()
                ],
            )
        )
    # Add dynamic filters to view
    self.update_dynamic_filters(dynamic_filters)
    return super(RecordView, self).index_view()
def _get_options_for_filter()
    if not has_request_context():
        return ()
    return tuple([(o.id, o.title) for o in Options.query.all()])