【发布时间】:2019-12-21 16:54:21
【问题描述】:
我有两个模型:User 和 ReferralKey,有这些要求:
- 在创建
User时,会自动创建ReferralKey并将其添加到数据库中 -
ReferralKey跟踪它推荐的用户 -
ReferralKey跟踪哪个用户拥有它
根据this 问题的答案,最好的解决方案似乎是在User 的构造函数中创建ReferralKey。其他两个的解决方案需要外键,而且看起来真的很乱——把表纠缠在一起,我还不如把它们放在同一个表中。
第一个的解决方案如下:
def User(model):
id = Column(BigInteger(), autoincrement=True, primary_key=True)
referral_key = relationship('ReferralKey', uselist=False)
...
def __init__(self):
self.referral_key = ReferralKey()
def ReferralKey(model):
id = Column(BigInteger(), autoincrement=True, primary_key=True)
user_id = Column(BigInteger(), ForeignKey('user.id', ondelete='SET NULL'), nullable=True)
这按预期工作,并解决了第一点和第三点。尝试解决第二个问题时会出现问题。这(出于某种原因)需要在 User 中使用新的外键,这需要在 User 和 ReferralKey 中声明 relationship 以(我猜)消除外键歧义:
def User(model):
id = Column(BigInteger(), autoincrement=True, primary_key=True)
referral_key = relationship('ReferralKey', uselist=False)
referrer_id = Column(BigInteger(), ForeignKey('referral_key.id', ondelete='SET NULL'))
referrer = relationship('ReferralKey', foreign_keys=['referrer_id'], backref='used_by')
...
def __init__(self):
self.referral_key = ReferralKey()
def ReferralKey(model):
__tablename__='referral_key'
id = Column(BigInteger(), autoincrement=True, primary_key=True)
user_id = Column(BigInteger(), ForeignKey('user.id', ondelete='SET NULL'), nullable=True)
user = relationship('User', foreign_keys=['user_id'])
我尝试了 relationship 和 ForeignKey 的所有不同排列,但总是得到相同的错误:
sqlalchemy.exc.CircularDependencyError: Can't sort tables for DROP; an unresolvable foreign key dependency exists between tables: referral_key, users. Please ensure that the ForeignKey and ForeignKeyConstraint objects involved in the cycle have names so that they can be dropped using DROP CONSTRAINT.
最终,我的问题是我只是不明白自己在做什么。为什么我需要更改User 表根本以跟踪ReferralKey 表上的内容? relationship 声明的目的是什么?为什么没有这个声明会模棱两可?如果User 有一个引用ReferralKey 的外键,而ReferralKey 有一个引用User 的外键——在删除的情况下,其中任何一个都应该设置为NULL,为什么SQL 需要比这更多的信息?
为什么我不能拥有:
def User(model):
id = Column(BigInteger(), autoincrement=True, primary_key=True)
def __init__(self):
ReferralKey(user_id=self.id)
def ReferralKey(model):
__tablename__='referral_key'
id = Column(BigInteger(), autoincrement=True, primary_key=True)
user_id = Column(BigInteger(), ForeignKey('user.id', ondelete='SET NULL'), nullable=True)
used_by = [list of user IDs]
def __init__(self, user_id):
if user_id:
self.user_id == user_id
这对我来说感觉更干净、更直观。如果我想添加(或删除!)推荐密钥,我几乎不必担心向User 添加东西,因为它主要独立于推荐密钥的功能。为什么我需要在user 表中添加一列来跟踪我希望ReferralKey 跟踪的内容?
基本上,我对此一无所知。有人介意帮助我吗?
【问题讨论】:
-
您能否详细说明关系:一个用户可以有零个或一个推荐密钥?推荐密钥总是链接到一个用户?哪个方向是一对多,哪个是一对多?
-
@AndiSchroff 创建用户时,他们只有一个与他们的帐户相关联的推荐密钥——他们拥有该密钥,以便其他用户可以使用它(一对一;ForeignKey on ReferralKey) .此外,推荐密钥应跟踪哪些用户在注册时使用了它(一对多;用户上的 ForeignKey)。我的部分问题还在于我不知道为什么这不能全部通过 ReferralKey 模型完成(为什么我们必须将两者纠缠这么多?)
标签: python postgresql sqlalchemy