2017-01-29 25 views
8

Silnik gier zapewnia mi klasę Player, która ma właściwość tylko do odczytu, aby identyfikować graczy. Chciałbym „przerobić” to w produkt SQLAlchemy na Column tak, że mogę zapytać graczy z nim tak:Zastępuje właściwość tylko do odczytu z kolumną tylko do odczytu, która ma tę samą wartość.

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') 

Oto co moja klasa aktualnie wygląda tak:

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) 

Następny chciałbym utworzyć interfejs "tylko do odczytu" dla użytkownika _uniqueid, aby użytkownicy interfejsu API nie mogli już zapisywać do zmiennej (cóż, mogą przez _uniqueid, ale to na nich spoczywa odpowiedzialność, ponieważ dostęp do niej powinien odbywać się za pośrednictwem nieprywatnego uniqueid).

myślę o nadpisanie oryginalnego uniqueid na nową:

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

To jest tylko do odczytu i „ukrywa” oryginalnego _uniqueid, zapobiegając nikogo od pisania do niego, chyba że celowo dostęp do prywatnej jednego (Nie będę nawet wymieniał tego w dokumentacji, tylko wystawię ten nieprywatny).

Jedynym problemem jest to, że całkowicie zastępuje starą, co oznacza, że ​​moje __init__ „s _uniqueid=self.uniqueid nie będzie działać z powodu self.uniqueid pomocą nowy getter, nie starego.

Tak więc podsumowałem, że chcę przekonwertować właściwość tylko do odczytu na coś typu "tylko do odczytu", które może być używane do wysyłania zapytań za pomocą SQLAlchemy. Czy to możliwe, a jeśli, jak?

+0

Najprawdopodobniej zależy to od implementacji 'game.Player.uniqueid'. Co umieszcza w słowniku instancji? Jak ustawić wartość, gdy trzeba ponownie nawilżyć instancję 'Player' z bazy danych? Ponieważ może to być trudne do zrozumienia dla bibliotek stron trzecich, generalnie nie polecam mieszania klas modeli i klas stron trzecich w ten sposób. – univerio

+0

@univerio Jest to tylko własność 'tylko do odczytu', która wykorzystuje trochę magii C. Zasadniczo, gdy zdarzy się wydarzenie 'player_join', silnik gry dostarcza 'index' łączącego gracza, a wykonanie' player = game.Player (index) 'daje mi obiekt, który ma teraz właściwość' uniqueid', którą można odczytać z niego . –

+0

Ale gdzie są przechowywane rzeczywiste dane dla 'uniqueid'? Mówisz, że jest obliczany na podstawie "indeksu"? A wszystko, czego potrzebujesz, aby ponownie nawodnić 'Player' jest jego indeksem? – univerio

Odpowiedz

1

Możesz użyć super, aby uzyskać dostęp do właściwości game.Player. Możemy przetestować za pomocą prostego typ rozszerzenia C utworzony z 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" 

powodu niepewnej dziedziczenie z typów rozszerzeń C, to może być lub może nie działać w zależności od tego, co dokładnie typ C magii game.Player używa.

Ponadto, ponieważ ORM omija __init__ gdy ładuje instancje z bazy danych, będziesz musiał zahaczyć w przypadku load w celu zainicjowanie typ game.Player.

+0

Przepraszam, wydaje mi się, że zupełnie zapomniałem o tym pytaniu ... Akceptowane i przegłosowane teraz, to naprawdę * działa *. –