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

anv*_*nvd 13 python postgresql sqlalchemy flask 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)
Run Code Online (Sandbox Code Playgroud)

错误:

ArgumentError: Column-based expression object expected for argument 'foreign_keys'; got: 'posts.id', type <class 'str'>
Run Code Online (Sandbox Code Playgroud)

don*_*mus 16

这里的一个问题是您当前正在尝试在关系中使用表列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')    
Run Code Online (Sandbox Code Playgroud)

如果没有,那么还有其他几个选择.首先,您可以在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')    
Run Code Online (Sandbox Code Playgroud)

注意在这个版本中,我们不需要将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')    
Run Code Online (Sandbox Code Playgroud)

  • 我并不真正关心你的赏金,我也不特别关心尝试完全复制你的表和数据库结构来帮助你解决一个相当简单的问题.我只是想提供指示......你知道,我怀疑你可能有能力做一些事情,比如查找文档**.例如,简单地看一下关系api就会告诉你`primary_join`应该是`primaryjoin` ... (4认同)
  • @anvd primary_join应该是主要加入.还注意到你在`foreign_keys`中使用的是表名,而不是类名,我相应地修改了我的答案.让我知道事情的后续! (2认同)
  • 显然问题不是那么简单.四天后有65次观看,我只有"猜测".顺便说一下,谢谢 (2认同)