Flask -Admin: Изменить порядок сортировки inline_models? - PullRequest
0 голосов
/ 04 августа 2020

В Flask -Admin, есть ли способ контролировать порядок списка, созданного inline_models? Кажется, что он выходит в порядке базы данных, то есть упорядочивается по первичному ключу ID.

То есть, если у меня есть Author, который has_many Books, а мой класс AuthorModelView имеет inline_models = (Books,), книги всегда упорядочиваются по book_id. Передача column_default_sort во встроенную модель, чтобы попытаться отсортировать (скажем) по заголовку или дате_покупки, не имеет никакого эффекта. Есть ли способ справиться с этим?

1 Ответ

1 голос
/ 12 августа 2020

enter image description here

Specify the order_by parameter when specifying the relationships, см. Документы . См. Примечание в конце, если вы хотите сортировать по указанному полю c во время выполнения.

Пример объявления модели для Автор -> Книги. Здесь мы упорядочиваем поле заголовка книги по возрастанию - 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.

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