我有一个名为
Player
, 的 Flask 模型
class Player:
id = Column(Integer, primary_key=True)
kills = Column(Integer)
bot_id = Column(Integer,ForeignKey("bots.id"))
bot = relationship("Bot",back_populates="player")
user_id = Column(Integer,ForeignKey("users.id"))
user = relationship("User",back_populates="player")
player_type = Column(String) # BOT or USER
Bot
和User
模型都有自己的属性。我想直接访问这些属性,而不是通过关系属性。这是因为我们的前端严重依赖于此。
例如,我不想使用
player.bot.screen_name
,而是想像 player.screen_name
那样访问它。
我可以通过使用以下代码来实现此目的,但我不想对每个属性都执行此操作,因为有很多属性。
@property
def screen_name(self):
if self.player_type == "BOT":
return self.bot.screen_name
elif self.player_type == "USER":
return self.user.screen_name
else:
return None
所以,我尝试了以下方法,
def __getattr__(self, attr):
if hasattr(self, attr):
return getattr(self, attr)
elif self.player_type == "BOT" and hasattr(self.bot, attr):
return getattr(self.bot, attr)
elif self.player_type == "USER" and hasattr(self.user, attr):
return getattr(self.user, attr)
else:
raise AttributeError(f"'{type(self).__name__}' object has no attribute '{attr}'")
但是,由于
getattr
,此代码会导致递归错误。
有其他方法可以实现这一点吗?
association_proxy
可能就是您正在寻找的。
下面是如何使用它的示例。 机器人的
screen_name
属性可在玩家对象中直接访问。
from sqlalchemy.ext.associationproxy import association_proxy
class Bot(db.Model):
__tablename__ = 'bots'
id = db.Column(db.Integer, primary_key=True)
player = db.relationship("Player",back_populates="bot")
screen_name = db.Column(db.String)
class Player(db.Model):
__tablename__ = 'players'
id = db.Column(db.Integer, primary_key=True)
# ...
bot_id = db.Column(db.Integer,db.ForeignKey("bots.id"))
bot = db.relationship("Bot",back_populates="player")
screen_name = association_proxy('bot', 'screen_name')
player = ...
print(player.screen_name)