New*_*Guy 13 python sqlalchemy
我有两个非常简单的模型.在我的Post模型中,应该有两个关系进入User表中.一个是帖子的所有者,一个是帖子的最后一个编辑.它们可以是不同的值,但两者都指向同一个User表.
我的模型是这样设置的
class Post(Base):
last_editor_id = Column(BigInteger, ForeignKey('users.id'), nullable=True)
last_editor = relationship('User', backref='posts', foreign_keys=[last_editor_id])
owner_id = Column(BigInteger, ForeignKey('users.id'), nullable=False, index=True)
owner = relationship('User', backref='posts', foreign_keys=[owner_id])
class User(Base):
'''This represents a user on the site'''
__tablename__ = 'users'
id = Column(BigInteger, primary_key=True, unique=True)
name = Column(BigInteger, nullable=False)
Run Code Online (Sandbox Code Playgroud)
当我尝试创建这些模型时,我收到以下错误
sqlalchemy.exc.ArgumentError: Error creating backref 'posts' on relationship 'Post.owner': property of that name exists on mapper 'Mapper|User|users'
Run Code Online (Sandbox Code Playgroud)
如何更正此问题,以便我可以在Post模型中维护两个forgeign键?
Doo*_*beh 22
错误告诉您,您已经使用post了一次名称作为backrefs,您需要做的就是给backref的唯一名称.这是一个完整的例子 - 我已经为Post类添加了一个id主键,还有一些__repr__s,所以我们得到了一些可读的输出.
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, BigInteger, ForeignKey, Integer
from sqlalchemy.orm import relationship, sessionmaker
Base = declarative_base()
engine = create_engine('sqlite://') ## In Memory.
Session = sessionmaker()
Session.configure(bind=engine)
session = Session()
class Post(Base):
__tablename__ = 'post'
id = Column(Integer, primary_key=True)
last_editor_id = Column(BigInteger, ForeignKey('users.id'), nullable=True)
last_editor = relationship('User', backref='editor_posts', foreign_keys=[last_editor_id])
owner_id = Column(BigInteger, ForeignKey('users.id'), nullable=False, index=True)
owner = relationship('User', backref='owner_posts', foreign_keys=[owner_id])
def __repr__(self):
return '<Post: {}>'.format(self.id)
class User(Base):
'''This represents a user on the site'''
__tablename__ = 'users'
id = Column(BigInteger, primary_key=True, unique=True)
name = Column(BigInteger, nullable=False)
def __repr__(self):
return '<User: {}>'.format(self.name)
Base.metadata.create_all(engine)
bob = User(name='Bob', id=1)
alice = User(name='Alice', id=2)
post = Post(owner=alice, last_editor=bob, id=1)
session.add(post)
session.commit()
bob = session.query(User).get(1)
print bob
# <User: Bob>
print bob.editor_posts
# [<Post: 1>]
print bob.owner_posts
# []
post = session.query(Post).get(1)
print post.owner
# <User: Alice>
print post.last_editor
# <User: Bob>
Run Code Online (Sandbox Code Playgroud)
现在,当您查询用户时,您可以询问该对象user.owner_posts或user.editor_posts.
一般来说,这是 backref 的命名问题。
由于 1:n 关系有时有点令人困惑,因此我始终将关系属性设置在单个站点上,以避免混淆。
那么 backref 名称始终是单数。并且关系属性始终位于外键引用的类中。
现在我对固定代码的建议:
class Post(Base):
last_editor_id = Column(BigInteger, ForeignKey('users.id'), nullable=True)
owner_id = Column(BigInteger, ForeignKey('users.id'), nullable=False, index=True)
class User(Base):
'''This represents a user on the site'''
__tablename__ = 'users'
id = Column(BigInteger, primary_key=True, unique=True)
name = Column(BigInteger, nullable=False)
owned_posts = relationship('Post', backref='owner')
edited_posts = relationship('Post', backref='last_editor')
Run Code Online (Sandbox Code Playgroud)
User现在,您可以获得 的所有拥有的帖子User.owned_posts以及帖子的所有所有者Post.owner。与last_edited 属性相同。
有关更多信息,您可以阅读如何建立关系的文档