2015-11-08 15 views
5

Załóżmy, że mam Peewee model, który wygląda mniej więcej następująco:Definiowanie pól wirtualnych peewee

class MyModel(peewee.Model): 
    a = peewee.IntegerField() 
    b = peewee.IntegerField() 

I pragnę dodać obiekt do tego modelu, co następuje:

@property 
    def diff(self): 
     return self.a - self.b 

ten czasami jest pomocne; teraz, jeśli Object jest instancją MyModel, mogę łatwo sprawdzić jej diff z Object.diff.

Co ja nie może zrobić to:

objects = list(MyModel.select().where(MyModel.diff < 17)) 

i to od MyModel.diff jest prosty własność, i prawdopodobnie jest zawsze większa niż 17. Nie jest to niczym MyModel.a < 17Expression .

Byłoby bardzo miło wystawić diff tak, jakby było to pole; więc użytkownik tego API nie będzie musiał wiedzieć, czy konkretna implementacja ma jako rzeczywiste pola i jako rzeczywiste pola i diff jako wirtualna, lub raczej a i diff jako rzeczywiste pola i b jako wirtualna.

Oczywiście, moim prawdziwym zamiarem jest wykorzystanie właściwości, które w niektórych przypadkach obejmują znacznie bardziej wyrafinowane obliczenia niż te przedstawione na stronie diff; Przykładem jest

@property 
def complicated_property(self): 
    if 17 <= self.a <= 173: 
     return a_complicated_math_function(self.a + self.b) 
    return another_complicated_math_function(self.a * self.b ** 2) 

Z drugiej strony może być bardzo proste właściwości, takich jak

@property 
def seven(self): 
    return 7 

Oznacza to, że nie może, na ogół, są przekształcane do SQL, ale raczej filtrować wyniki po pobraniu z bazy danych.

Czy to możliwe?

Aktualizacja

Właśnie odkryto Peewee Playhouse hybrydowy metody/właściwości. Stanowią one częściowe rozwiązanie mojego pytania.

Na przykład moja metoda diff może stać się hybrid_property i działać zgodnie z oczekiwaniami. Mój complicated_property nie może stać się jednym, a przynajmniej tak się wydaje; warunek if na początku powróci albo True lub False stale i nie będzie działał jako funkcja.

Peewee prawdopodobnie ma jeszcze trochę magii, która się tam kryje; Będę dalej przeglądał i raportował moje odkrycia.

Odpowiedz

4

Brzmi jak hybrid_property będzie tym, czego szukasz. Oto the hybrid methods documentation

Jak do aktualizacji, jeśli właśnie czytać trochę dalej w docs ...

@hybrid_property 
def radius(self): 
    return abs(self.length)/2 

@radius.expression 
def radius(cls): 
    return fn.ABS(cls.length)/2 

Tak więc widać dwie funkcje dla tej samej nieruchomości, radius. Pierwsza funkcja zostanie wywołana po wywołaniu instancji modelu. Drugi po wywołaniu w zapytaniu.

Możecie napisać:

@hybrid_property 
def complicated_property(self): 
    if 17 <= self.a <= 173: 
     return a_complicated_math_function(self.a + self.b) 
    return another_complicated_math_function(self.a * self.b ** 2) 

@complicated_property.expression 
def complicated_property(cls): 
    # Here you will need to use a CASE statement most likely. 
    # If you want to turn it into SQL, you obviously need to know 
    # what SQL you want to turn it into... 
    return case(
     None, 
     (cls.a.between(17, 173), fn.math(fn.more_math(cls.a, 1.23))), 
     default=fn.another_complicated_math(cls.a)) 
+0

Dzięki! I akceptuję również twoją krytykę ... i dzięki za peewee! – Bach