使用 alembic 添加关系 backref order_by

Add relationship backref order_by with alembic

我最近将 Alembic 添加到我的 Flask 项目中,现在我使用 order_by 排序的 SQLAlchemy 关系不再有效。我相信这是因为 运行 的迁移文件没有选择 order_by 参数,我不确定如何获取它。

我的模型看起来像...

class Project(db.Model):
    __tablename__ = 'project'

    id = db.Column(db.Integer(), primary_key=True)


class User(db.Model):
    __tablename__ = 'user'

    id = db.Column(db.Integer(), primary_key=True)
    project_id = db.Column(db.ForeignKey(Project.id, ondelete="cascade"), index=True, nullable=False)
    project = db.relationship(Project, backref='members', order_by="User.id.desc()")

在 Alembic 迁移中,我看到以下...

    ...

op.create_table('user',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('project_id', sa.Integer(), nullable=False),
    ...
    sa.ForeignKeyConstraint(['project_id'], ['project.id'], ondelete='cascade'),
)
op.create_index(op.f('ix_user_project_id'), 'user', ['project_id'], unique=False)

...

查看迁移,我不太确定 SQLAlchemy 实际上是如何处理这种关系的,因为我没有在任何地方看到任何类型的反向引用,我猜 SQLAlchemy 只是 运行 一个查询来获取项目的用户。

如有任何帮助,我们将不胜感激!

迁移文件是正确的,在数据​​库级别没有 backref,只有创建的外键将用户实体与项目链接起来。 事实上,正如您所说,sqlalchemy 将在您第一次访问用户的 user.project 属性时发出一个新查询,加入 project_id 字段。附带说明一下,如果您想在查询用户时完全加入项目的列,则应该使用 joinedload option

关于关系声明中使用的“order_by”,它只适用于加载的关系,例如官方文档中的这个例子:

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", order_by="Child.id")

在上面的示例中,当访问 parent.children 时,结果将按 children 的 ID 排序。

在您的情况下,这没有意义,因为它是多对一的关系,并且对于每个用户,您只有一个项目。也许你应该把它移到项目模型中:

class Project(db.Model):
    __tablename__ = 'project'

    id = db.Column(db.Integer(), primary_key=True)
    members = db.relationship('User', backref='project', order_by='User.id.desc()')

这样,每当您访问项目的 project.members 属性时,您将获得一个排序的用户列表。