一个对象是同一个表的两个外键

时间:2015-10-02 00:32:19

标签: python postgresql flask sqlalchemy flask-sqlalchemy

我需要有一个与两个用户关联的帖子。作者和主持人。我正在努力尝试这段代码

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    ...
    post = db.relationship('Post', foreign_keys=['posts.id'], backref='post_user', lazy='dynamic')
    post_blame = db.relationship('Post', foreign_keys=['posts.moderated_by'], backref='post_blame', lazy='dynamic')    

class Post(db.Model):
    __tablename__ = 'posts'
    id = db.Column(db.Integer, primary_key=True)
    ...
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    moderated_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)

错误:

ArgumentError: Column-based expression object expected for argument 'foreign_keys'; got: 'posts.id', type <class 'str'>

1 个答案:

答案 0 :(得分:14)

此处的一个问题是您当前正在尝试在关系foreign_keys中使用表列,而不是类属性。

也就是说,您应该使用posts.id而不是Post.id。 (事实上​​,要引用表格列,您需要使用posts.c.id)。

因此,如果您将原始代码更正为:

,则原始代码可能会有效
class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    ...
    post = db.relationship('Post', foreign_keys='Post.id', backref='post_user', lazy='dynamic')
    post_blame = db.relationship('Post', foreign_keys='Post.moderated_by', backref='post_blame', lazy='dynamic')    

如果没有,那么还有其他几个选项。首先,您可以在Post类中建立这些关系,其中sqlalchemy找不到外键关系的模糊性较小。像

这样的东西
class Post(db.Model):
    __tablename__ = 'posts'
    id = db.Column(db.Integer, primary_key=True)
    ...
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    moderated_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    post_user = db.relationship(User, foreign_keys=author_id, backref='post', lazy='dynamic')
    post_blame = db.relationship(User, foreign_keys=moderated_by, backref='post_blame', lazy='dynamic')    

请注意,在此版本中,我们不需要将foreign_keys值作为字符串传递,我们可以直接引用范围中的列。

或者,如果您希望在用户中建立这些关系,您可能需要使用sqlalchemy提供primaryjoin更多信息......或许类似于:

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    ...
    post = db.relationship('Post', primaryjoin='User.id == Post.id', backref='post_user', lazy='dynamic')
    post_blame = db.relationship('Post', foreign_keys='User.id == Post.moderated_by', backref='post_blame', lazy='dynamic')