Flask-Admin中的自定义和可排序列

Neo*_*oID 5 sqlalchemy flask flask-sqlalchemy flask-admin

我正在使用Flask-Admin和SQLAlchemy,并且很难在listview中创建自定义的可排序字段.我是这样的用户和照片模型:

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    photos = db.relationship('Photo', backref='user', lazy='dynamic', cascade='all, delete-orphan')

class Photo(db.Model):
    __tablename__ = 'photos'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), index=True)
    filename = db.Column(db.String(128))
    publish = db.Column(db.Boolean, index=True)
    date = db.Column(db.DateTime, default=datetime.now)
Run Code Online (Sandbox Code Playgroud)

然后我创建一个自定义视图(UserView),创建一个名为'test'的自定义字段,并使用column_formatters重写它以包含照片的数量.虽然结果是正确的,但该字段不可排序.还有另一种解决方法吗?

class UserView(sqla.ModelView):

    column_list = ('username', 'test')

    def _count_formatter(view, context, model, name):
        return model.photos.count()

    column_formatters = {
        'test': _count_formatter
    }

    def is_accessible(self):
        return login.current_user.is_authenticated
Run Code Online (Sandbox Code Playgroud)

Dau*_*ros 8

您可以使用SQLAlchemy的混合属性,这对于定义作用于模型类的高级函数很有用.

修改后的模型:

from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy import select, func

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    photos = db.relationship('Photo', backref='user', lazy='dynamic', cascade='all, delete-orphan')

    @hybrid_property
    def number_of_photos(self):
        return self.photos.count()

    @number_of_photos.expression
    def number_of_photos(cls):
        return select([func.count(Photo.id)]).where(Photo.user_id == cls.id).label('number_of_photos')
Run Code Online (Sandbox Code Playgroud)

我们刚刚添加了新的混合属性.我们可以像User实例上的普通表列一样访问它:user.number_of_photos.

并修改UserView:

class UserView(sqla.ModelView):
    column_list = ('username', 'number_of_photos')
    column_sortable_list = ['username', 'number_of_photos']

    def is_accessible(self):
        return login.current_user.is_authenticated
Run Code Online (Sandbox Code Playgroud)

在这里,我们必须明确定义可排序/可见列的列表.