【问题标题】:Flask-Admin: Change sort order of inline_models?Flask-Admin:更改 inline_models 的排序顺序?
【发布时间】:2020-11-24 11:24:40
【问题描述】:

在Flask-Admin中,有没有办法控制inline_models生成的列表的顺序?它似乎是按数据库顺序出现的,即按 ID 主键排序。

也就是说,如果我有一个 Author 有多个 Books,并且我的 AuthorModelView 类有 inline_models = (Books,),那么这些书总是按 book_id 排序的。将column_default_sort 传递给内联模型,尝试按(比如)title 或 date_purchased 排序,没有效果。有什么办法可以处理吗?

【问题讨论】:

    标签: python flask flask-admin


    【解决方案1】:

    在指定关系时指定order_by 参数see docs。如果您想在运行时按特定字段排序,请参阅最后的注释。

    Author -> Books 的模型声明示例。在这里,我们按书名字段升序排序 - order_by='Book.title.asc()'

    class Author(db.Model):
        __tablename__ = 'authors'
    
        id = db.Column(db.Integer, primary_key=True)
        first_name = db.Column(db.Text(length=255), nullable=False)
        last_name = db.Column(db.Text(length=255), nullable=False)
        books = db.relationship("Book", order_by='Book.title.asc()', cascade="all,delete-orphan", backref=db.backref('author'))
    
        def __str__(self):
            return f"ID: {self.id}; First Name: {self.first_name}; Last Name: {self.last_name}"
    
    
    class Book(db.Model):
    
        __tablename__ = 'books'
    
        id = db.Column(db.Integer, primary_key=True)
        author_id = db.Column(db.Integer, db.ForeignKey('authors.id'), nullable=False, index=True)
        title = db.Column(db.Text(length=255), nullable=False)
    
        def __str__(self):
            return f"ID: {self.id}; Title: {self.title}; Author ID: {self.author_id}"
    

    单个文件完整示例:

    from faker import Faker
    import click
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    from flask_admin import Admin
    from flask_admin.contrib import sqla
    
    db = SQLAlchemy()
    
    
    class Author(db.Model):
        __tablename__ = 'authors'
    
        id = db.Column(db.Integer, primary_key=True)
        first_name = db.Column(db.Text(length=255), nullable=False)
        last_name = db.Column(db.Text(length=255), nullable=False)
        books = db.relationship("Book", order_by='Book.title.asc()', cascade="all,delete-orphan", backref=db.backref('author'))
    
        def __str__(self):
            return f"ID: {self.id}; First Name: {self.first_name}; Last Name: {self.last_name}"
    
    
    class Book(db.Model):
    
        __tablename__ = 'books'
    
        id = db.Column(db.Integer, primary_key=True)
        author_id = db.Column(db.Integer, db.ForeignKey('authors.id'), nullable=False, index=True)
        title = db.Column(db.Text(length=255), nullable=False)
    
        def __str__(self):
            return f"ID: {self.id}; Title: {self.title}; Author ID: {self.author_id}"
    
    
    app = Flask(__name__)
    
    app.config['SECRET_KEY'] = '123456790'
    app.config['SQLALCHEMY_ECHO'] = True
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sample.sqlite'
    
    db.init_app(app)
    
    
    @app.cli.command('create-database', short_help='Create Authors database')
    @click.option('--count', default=100, help='Number of authors (default 100)')
    def create_database(count):
    
        """
            Create database with "count" authors
        """
    
        db.drop_all()
        db.create_all()
        _faker = Faker()
        for _ in range(0, count):
            _author = Author(
                first_name=_faker.first_name(),
                last_name=_faker.last_name(),
            )
            db.session.add(_author)
            for _ in range(0, _faker.pyint(1, 20)):
                _book = Book(
                    title=_faker.sentence(),
                    author=_author
                )
                db.session.add(_book)
    
        db.session.commit()
    
    
    class AuthorView(sqla.ModelView):
    
        # default sort: last_name ascending
        column_default_sort = ('last_name', False)
    
        inline_models = (Book,)
    
    
    # Flask views
    @app.route('/')
    def index():
        return '<a href="/admin/">Click me to get to Admin!</a>'
    
    
    admin = Admin(app, template_mode="bootstrap3")
    admin.add_view(AuthorView(Author, db.session))
    
    
    if __name__ == '__main__':
        app.run()
    

    运行以下命令初始化 SQLite DB。

    flask create-database --count 100
    

    如果您想在运行时更改排序字段,请覆盖视图的 get_one() 方法并使用 Python 直接对已检测列表进行排序。例如,按 ISBN 字段而不是标题排序:

    class Author2View(sqla.ModelView):
        def get_one(self, id):
            _author = super().get_one(id)
            _author.books = sorted(_author.books, key=lambda book: book.isbn)
            return _author
    
        # default sort: last_name ascending
        column_default_sort = ('last_name', False)
    
        inline_models = (Book,)
    
    admin.add_view(Author2View(Author, db.session, name="Author 2", endpoint='author-2'))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-24
      • 1970-01-01
      • 1970-01-01
      • 2019-02-22
      • 2018-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多