我可以直接访问 Flask SQLAlchemy 模型中的嵌套属性吗?

问题描述 投票:0回答:1

我有一个名为

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
,此代码会导致递归错误。

有其他方法可以实现这一点吗?

python flask sqlalchemy orm flask-sqlalchemy
1个回答
0
投票

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)
© www.soinside.com 2019 - 2024. All rights reserved.