简体   繁体   English

SQLAlchemy - “可选”外键/零对一关系

[英]SQLAlchemy - "Optional" Foreign Key / Zero-to-One relationship

I am trying to switch from raw SQL to SQLAlchemy and I am struggling modelling a relationship between users and teams.我正在尝试从原始 SQL 切换到 SQLAlchemy,并且正在努力为用户和团队之间的关系建模。 In this situation, a team has a list of users and a user can be in zero or one team .在这种情况下,一个团队有一个用户列表,一个用户可以在零个或一个团队中

Somethin like a "optional foreign key" in the table User, referencing to team.id could work, but it would have to be nullable which is not the best manner.类似于表 User 中的“可选外键”,引用 team.id 可以工作,但它必须可以为空,这不是最好的方式。

When using raw SQL, I usually create a third table TeamUser(user_id, team_id) with user_id as primary key .使用原始 SQL 时,我通常会创建第三个表TeamUser(user_id, team_id)user_id 作为主键

It is entirely possible to replicate this in SQLAlchemy by creating a table, but the python code that need to be written to use those objects becomes less clear.完全有可能通过创建表在 SQLAlchemy 中复制这一点,但是需要编写使用这些对象的 python 代码变得不太清楚。

For example :例如 :

add a user to a team :将用户添加到团队:

db.session.add(TeamUser(user_id=user.id, team_id=team.id)) 
#instead of
team.users.append(user)

access the team of a user:访问用户的团队:

user.team.team (user.team is now the couple (user_id, team_id))

get the list of users as User objects:获取用户列表作为 User 对象:

map(lambda team_user: team_user.user, team.users)  
#instead of
team.users

So my question is : is there a way to both model this user/team situation and keep an easy syntax while using SQLAlchemy objects?所以我的问题是:有没有办法在使用 SQLAlchemy 对象时对这种用户/团队情况进行建模并保持简单的语法?

I have looked at primary join but it doesn't seem to answer this problem.我看过主要连接,但它似乎没有回答这个问题。 (but maybe I'm wrong) (但也许我错了)

If you really want to use a join table, take a look at association_proxy .如果您真的想使用连接表,请查看association_proxy

For a one to many relationship, a foreign key is simpler.对于一对多关系,外键更简单。 The player (user is likely a reserved word) has a reference to a team:玩家(用户可能是保留字)引用了一个团队:

class Player(Base):
    __tablename__ = 'player'
    id = Column(Integer, primary_key=True)
    team_id = Column(Integer, ForeignKey('team.id'))
    team = relationship('Team')

And a team has a list of players:一个团队有一个球员名单:

class Team(Base):
    __tablename__ = 'team'
    id = Column(Integer, primary_key=True)
    players = relationship('Player', back_populates='team')

Then you can add a player via然后你可以通过添加一个播放器

team.players.append(player) # Player() object

Get a player's team (may be None )获取一个玩家的团队(可能是None

team: Team = player.team

Get the list of players as Player objects获取玩家列表作为 Player 对象

team.players

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM