在指定关系时指定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'))