2017-01-29 3 views
8

Ядро игры предоставляет мне класс Player, который имеет свойство uniqueid только для чтения, чтобы идентифицировать игроков. Я хотел бы, чтобы «преобразовать» это в SQLAlchemy-х Column, так что я могу запросить игрок с ним, как это:Переопределить свойство только для чтения с только столбцом, доступным только для чтения.

query = session.query(Player).filter(Player.uniqueid=='STEAM_0:0:1234567') 
player = query.one_or_none() 
if player is None: 
    player = Player(uniqueid='STEAM_0:0:1234567') 

Вот что мой класс в настоящее время выглядит следующим образом:

class Player(game.Player, db.Model): 
    _uniqueid = Column('uniqueid', String(21), unique=True, nullable=False) 

    def __init__(self, index, **kwargs): 
     game.Player.__init__(index) # initializes uniqueid 
     db.Model.__init__(_uniqueid=self.uniqueid, **kwargs) 

Далее я хотел бы создайте интерфейс для чтения только для _uniqueid, так что пользователи API больше не смогут писать переменную (ну, они могут через _uniqueid, но это зависит от их ответственности, поскольку доступ к ней должен происходить через не-частный uniqueid).

Я думаю, переопределяет оригинальный uniqueid с новым:

@property 
def uniqueid(self): 
    return self._uniqueid 

Это только для чтения и «шкуры» оригинальной _uniqueid, предотвращающие кого писать к нему, если они намеренно не получить доступ к закрытому один (Я даже не буду перечислять его в документации, я покажу только не-частный).

Единственная проблема заключается в том, что эта полностью отменяет старую, а это означает, что мои __init__ «ы _uniqueid=self.uniqueid не будет работать из-за self.uniqueid использованием новый добытчика, а не старый.

Итак, я хочу, чтобы преобразовать свойство только для чтения в только что доступное для чтения то, что можно использовать для запроса с помощью SQLAlchemy. Возможно ли это, и если, как?

+0

Это, скорее всего, зависит от того, как реализован «game.Player.uniqueid». Что он вкладывает в словарь экземпляра? Как вы устанавливаете значение, когда вам нужно повторно увлажнить экземпляр «Player» из базы данных? Поскольку это может быть трудно объяснить для сторонних библиотек, я обычно не рекомендую смешивать классы моделей и классы сторонних разработчиков, подобные этому. – univerio

+0

@univerio Это просто свойство «только для чтения», которое использует некоторую магию C. В основном, когда происходит событие 'player_join', игровой движок предоставляет« индекс »присоединяющегося игрока, а выполнение« player = game.Player (index) »дает мне объект, который теперь имеет свойство« uniqueid », читаемое из него , –

+0

Но где хранятся фактические данные для 'unique unique'? Вы говорите, что он вычисляется из 'index'? И все, что вам нужно для регидратации «Player», является его индексом? – univerio

ответ

1

Для доступа к объекту недвижимости game.Player вы можете использовать super. Мы можем проверить с помощью простого типа расширения C, созданный с Cython:

# game.pyx 
cdef class Player: 
    cdef int index; 

    def __init__(self, index): 
     self.index = index 

    @property 
    def uniqueid(self): 
     return "foo" 


# test.py 
class Player(game.Player, Base): 
    __tablename__ = "player" 

    id = Column(Integer, primary_key=True) 
    _uniqueid = Column('uniqueid', String(21), unique=True, nullable=False) 

    def __init__(self, index, **kwargs): 
     game.Player.__init__(self, index) # initializes uniqueid 
     Base.__init__(self, _uniqueid=super().uniqueid, **kwargs) 

    @property 
    def uniqueid(self): 
     return self._uniqueid 

print(Player(1).uniqueid) # "foo" 

Из-за ненадежности унаследовав от типов расширения C, это может быть или может не работать в зависимости от того, что магия C game.Player типа использует.

Кроме того, поскольку ORM обходит __init__ когда он загружает экземпляры из базы данных, вам придется внедриться в load случае для того, чтобы инициализировать game.Player типа.

+0

Извините, похоже, я полностью забыл этот вопрос ... Принял и поддержал сейчас, это действительно * работает *. –

Смежные вопросы