Flask-Admin:更改 inline_models 的排序顺序?
Flask-Admin: Change sort order of inline_models?
在Flask-Admin中,有没有办法控制inline_models
生成的列表的顺序?它似乎是按数据库顺序出现的,即按 ID 主键排序。
也就是说,如果我有一个 Author
has_many Books
,而我的 AuthorModelView class 有 inline_models = (Books,)
,那么书籍总是按book_id。将 column_default_sort
传递给内联模型,尝试按(比如)标题或 date_purchased 排序,但没有任何效果。有什么办法可以解决这个问题吗?
指定关系时指定 order_by
参数,see docs。如果您想在运行时按特定字段排序,请参阅末尾的注释。
作者 -> 书籍的模型声明示例。在这里,我们对书名字段进行升序排序 - 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'))
在Flask-Admin中,有没有办法控制inline_models
生成的列表的顺序?它似乎是按数据库顺序出现的,即按 ID 主键排序。
也就是说,如果我有一个 Author
has_many Books
,而我的 AuthorModelView class 有 inline_models = (Books,)
,那么书籍总是按book_id。将 column_default_sort
传递给内联模型,尝试按(比如)标题或 date_purchased 排序,但没有任何效果。有什么办法可以解决这个问题吗?
指定关系时指定 order_by
参数,see docs。如果您想在运行时按特定字段排序,请参阅末尾的注释。
作者 -> 书籍的模型声明示例。在这里,我们对书名字段进行升序排序 - 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'))