Jam*_*sis 1 python postgresql sqlalchemy relational-database
我正在代码中设置数据库,但在尝试弄清楚如何按照我想要的方式建立多对多关系时遇到困难。
基本上,我有一个User班级,其中有一个与班级的 m2m Team。事实上,一个团队有很多用户,一个用户可以是多个团队的一部分。到目前为止一切都很好。当我想向团队的用户授予“管理员”权限时,问题就出现了。
我尝试使用关联对象,但我不知道如何将关系标记为管理员。因此,我创建了第二个映射表,将团队映射到用户表中的管理员。如图所示:
Base = declarative_base()
# Many to Many relationship mapping tables
user_team_map = Table(
'user_team_map', Base.metadata,
Column('user_id', Integer, ForeignKey('users.id'), primary_key=True),
Column('team_id', Integer, ForeignKey('teams.id'), primary_key=True)
)
admin_team_map = Table(
'admin_team_map', Base.metadata,
Column('user_id', Integer, ForeignKey('users.id'), primary_key=True),
Column('team_id', Integer, ForeignKey('teams.id'), primary_key=True)
)
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
first_name = Column(String(24), nullable=False)
teams = relationship('Team', secondary=user_team_map, back_populates='users')
admin_of = relationship('Team', secondary=admin_team_map, back_populates='users')
class Team(Base):
__tablename__ = 'teams'
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
users = relationship('User', secondary=user_team_map, back_populates='teams')
admins = relationship('User', secondary=admin_team_map, back_populates='teams')
Run Code Online (Sandbox Code Playgroud)
当我尝试创建这些表时,我得到:
ValueError: Bidirectional attribute conflict detected: Passing object <User at 0x7f2089d7dcc0> to attribute "Team.admins" triggers a modify event on attribute "Team.users" via the backref "User.teams".
我当然不是数据库向导,所以我想这是我的整体方法是不正确的。我应该如何去实现我想要的关系?如果我应该使用关联对象我该怎么做?
(资格:我不了解 SQLAlchemy,所以我无法用这些术语回答。我将用Relational-Database和SQL术语回答:我确信您可以弄清楚实现。我使用的术语仅是关系型)。
是的,错误消息是有效的,即使错误消息文本可能不是特定的或没有指示您的问题,因为您确实有重复项(在数据库或 ORM 中不可接受)。例如。根据资格,我不会使用术语“*定向”,因为关系在关系数据库或 SQL 中没有方向(它们有父级和子级)。
这个问题有两个层次,我会按逻辑顺序解释。第一个层次是数据库存储,第二个层次是存储转换为类的问题。
首先需要了解物理层面。尽管它通常是逻辑设计的结果,但似乎存在一个差距:您在没有正式考虑逻辑的情况下就进入了物理。
你拥有的是一个关联表user_team_map。它与 关联users,teams并将 n 对 n 关系解析为两个 0 对 n 关系,每个关系一个到父级。(我也不会使用这个词map。)

然后你需要确定:
each team has 0-to-n has admins(哪个是users)
但是您“无法弄清楚如何将关系标记为管理员”,因此您将整个user_team_map结构复制到admin_team_map.
user成为admin其中的一个。teamusersteam我们只需在表中将 an“标记”user为 an即可。关联表仅包含对两个父级的引用,向其中添加一列会将其移出关联表的类别,进入普通表。adminuser_team-map


each team has 0-to-n adminseach team has 0-to-1 adminMemberName & AdminName角色名称为UserName由于“理论家”和“作者”将1960年代的前关系系统宣传和营销为“关系”,在“文献”和“教科书”中,存在很多混乱。生成的 RFS 没有完整性;力量; 或关系系统的速度。无论如何,这就是 ORM 使用的内容,这就是您正在使用的内容,所以我将提供它。
如果遵循这些声称是“关系性”的指示,就会得出这样的结果。

Foreign Key引用,以及由此导致的循环引用问题。如果我们只修复这两个错误。

Record Id。UserName)不能被删除:如果你这样做[1.4],你将允许重复的行(不是记录),这是被禁止的。Record Ids,则将其提升为关系型 [1.3]。您使用的类中似乎存在理解和实现错误。这是一个经典的例子,在使用 ORM 时非常常见。当底层存储没有被正确理解或实现时,问题就会变得更加复杂。
我相信你会实现[1.5]:

如果您想了解有关关系的更多信息,以及它们如何在 SQL 级别(承载逻辑级别的所有可能性)实现,请阅读此答案(仅限第一部分)。