Flask-SQLAlchemy,如何对多对多关系的结果进行排序?

Flask-SQLAlchemy,How to sort results in Many-to-Many Relationship?

我正在使用 flask-sqlalchemy。

我想在多对多关系中添加一个 ORDER 列。

我的模特:

image_category_association = db.Table('category_image_relation',
    db.Column('id', db.Integer, primary_key=True),
    db.Column('category_id', db.Integer, db.ForeignKey('image_category.category_id')),
    db.Column('image_id', db.Integer, db.ForeignKey('image.image_id')),
    db.Column('order', db.Integer, unique=True, autoincrement=True)
)

class ImageCategory(db.Model):
    __bind_key__ = 'ads'
    __tablename__ = 'image_category'

    category_id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), default='')
    add_time = db.Column(db.Integer, default=0)
    images = db.relationship('Image', secondary=image_category_relation, backref='categories', lazy='dynamic')


class Image(db.Model):
    __bind_key__ = 'ads'
    __tablename__ = 'image'

    image_id = db.Column(db.Integer, primary_key=True)
    add_time = db.Column(db.Integer, default=0)
    hash = db.Column(db.String(64), default='')
    url = db.Column(db.String(255), default='')

category = ImageCategory.query.get(1)
category.images.append(image1, image2, image3)
images = category.images.all()  # order by the ORDER column

是否可以更新 table 中的 ORDER 列值 image_category_association?

以及如何按 ORDER 列对 category.images.all() 顺序进行排序。

使用 association object - 请参阅下面的独立示例(我遗漏了您的一些字段)。 ImageCategoryToImageAssociation class 中的顺序是 created/updated - 请参阅 build_db 方法以了解其使用方法。

还要注意 ImageCategory images 属性 db.relationship 定义中的 order_by="ImageCategoryToImageAssociation.order" - category_1 的图像插入乱序但查询数据库 returns 它们按排序顺序排列。

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'super-secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)


class ImageCategoryToImageAssociation(db.Model):
    __tablename__ = 'image_categories_to_image_association'
    image_category_id = db.Column(db.Integer, db.ForeignKey('image_categories.id'), primary_key=True)
    image_id = db.Column(db.Integer, db.ForeignKey('images.id'), primary_key=True)
    order = db.Column(db.Integer, default=0)
    image = db.relationship("Image", back_populates="categories")
    category = db.relationship("ImageCategory", back_populates="images")


class ImageCategory(db.Model):
    __tablename__ = 'image_categories'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), unique=True)
    images = db.relationship(ImageCategoryToImageAssociation, back_populates="category", order_by="ImageCategoryToImageAssociation.order")


class Image(db.Model):
    __tablename__ = 'images'
    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String(255), default='')
    categories = db.relationship(ImageCategoryToImageAssociation, back_populates="image")


@app.route('/')
def index():

    _html = ""
    categories = ImageCategory.query.all()
    for category in categories:
        _html += "<h4>Category : {category}</h4>".format(category=category.name)
        _html += "<ul>"
        for assoc in category.images:
            _html += "<li>Image : {url}; Order: {order}</li>".format(url=assoc.image.url, order=assoc.order)

        _html += "</ul>"

    return _html


def build_db():

    db.drop_all()
    db.create_all()

    # Add Categories
    category_1 = ImageCategory(name="First Category")
    db.session.add(category_1)
    category_2 = ImageCategory(name="Second Category")
    db.session.add(category_2)

    # Add Images
    image_1 = Image(url="First Image")
    db.session.add(image_1)
    image_2 = Image(url="Second Image")
    db.session.add(image_2)

    image_3 = Image(url="Third Image")
    db.session.add(image_3)

    # Associate images with category 1
    a_1 = ImageCategoryToImageAssociation(order=0)
    a_1.image = image_1
    category_1.images.append(a_1)

    a_2 = ImageCategoryToImageAssociation(order=2)
    a_2.image = image_2
    category_1.images.append(a_2)

    a_3 = ImageCategoryToImageAssociation(order=1)
    a_3.image = image_3
    category_1.images.append(a_3)

    # Associate images with category 2 in reverse order
    a_1 = ImageCategoryToImageAssociation(order=2)
    a_1.image = image_1
    category_2.images.append(a_1)

    a_2 = ImageCategoryToImageAssociation(order=1)
    a_2.image = image_2
    category_2.images.append(a_2)

    a_3 = ImageCategoryToImageAssociation(order=0)
    a_3.image = image_3
    category_2.images.append(a_3)

    db.session.commit()


@app.before_first_request
def before_first_request():
    build_db()

if __name__ == '__main__':
    app.run()