使用基类的属性/属性作为表列?

时间:2016-07-28 10:08:59

标签: python python-3.x inheritance properties sqlalchemy

游戏引擎为我提供了一个Player类,其中包含steamid属性(来自C ++,这只是Python中的基本示例):

# game_engine.py

class Player:

    def __init__(self, steamid):
        self.__steamid = steamid

    @property
    def steamid(self):
        return self.__steamid

然后我在添加gold属性时继续子类化该类:

# my_plugin.py

class MyPlayer(game_engine.Player, Base):
    gold = Column(Integer)

现在我需要将播放器的gold存储到数据库中,并将播放器的steamid作为识别播放器的主键。如何告诉SQLAlchemy使用基类的steamid属性作为主键?

这是我试过的傻事:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property

import game_engine

Base = declarative_base()

class Player(game_engine.Player, Base):
    __tablename__ = 'player'

    _steamid = game_engine.Player.steamid

    @hybrid_property
    def steamid(self):
        return type(self)._steamid.__get__(self)

但是,这是一个长镜头......

sqlalchemy.exc.ArgumentError: Mapper Mapper|Player|player could not assemble any primary key columns for mapped table 'player'

2 个答案:

答案 0 :(得分:2)

这比你想象的要简单。下面的解决方案大致相当于r-m-n中的解决方案,但更简单,因为它使用现代声明性映射。不需要@hybrid_property,您可以从父类继承steamid

# my_plugin.py

class MyPlayer(game_engine.Player, Base):

    def __init__(self, steamid, gold):
        super().__init__(steamid)
        self._id = self.steamid
        self.gold = gold

    _id = Column('steamid', Integer, primary_key=True)
    gold = Column(Integer)

答案 1 :(得分:1)

这可以使用classical mapping

完成
from sqlalchemy import Column, Integer, Table
from sqlalchemy.orm import mapper
from sqlalchemy.ext.hybrid import hybrid_property


class MyPlayer(Player):
    def __init__(self, steamid, gold):
        super().__init__(steamid)
        self.gold = gold
        self._steamid = super().steamid


player = Table('player', Base.metadata,
    Column('_steamid', Integer, primary_key=True),
    Column('gold', Integer),
)


mapper(MyPlayer, player)