2010-03-05 19 views
15

Czy istnieje sposób przeprowadzania sprawdzania poprawności na obiekcie po (lub w) ustawieniach właściwości, ale przed zatwierdzeniem sesji? Na przykład mam model domeny Device, który ma właściwość mac. Chciałbym upewnić się, że właściwość mac zawiera poprawną i odkażoną wartość mac przed dodaniem lub zaktualizowaniem w bazie danych.Czy istnieje sposób przezroczystego wykonywania sprawdzania poprawności obiektów SQLAlchemy?

Wygląda na to, że podejście Pythoniczne polega na wykonywaniu większości czynności jako właściwości (w tym SQLAlchemy). Gdybym to zakodował w PHP lub Javie, prawdopodobnie wybrałbym metodę getter/setter w celu ochrony danych i zapewniłaby mi elastyczność w radzeniu sobie z tym w samym modelu domeny.

public function mac() { return $this->mac; } 
public function setMac($mac) { 
    return $this->mac = $this->sanitizeAndValidateMac($mac); 
} 
public function sanitizeAndValidateMac($mac) { 
    if (! preg_match(self::$VALID_MAC_REGEX)) { 
     throw new InvalidMacException($mac); 
    } 
    return strtolower($mac); 
} 

Co to jest Pythonowy sposób radzenia sobie z tego typu sytuacjami za pomocą SQLAlchemy?

(Chociaż jestem świadomy, że sprawdzanie poprawności i powinny być obsługiwane w innym miejscu (tj. Ramy sieci) Chciałbym dowiedzieć się, jak obsługiwać niektóre z tych zasad walidacji specyficzne dla domeny, ponieważ są one często pojawiają się.)

UPDATE

wiem, że mogę używać property to zrobić w normalnych okolicznościach. Kluczową częścią jest to, że używam SQLAlchemy z tymi klasami. Nie rozumiem dokładnie, jak SQLAlchemy wykonuje swoją magię, ale podejrzewam, że samodzielne tworzenie i przesłonięcie tych właściwości może prowadzić do niestabilnych i/lub nieprzewidywalnych wyników.

Odpowiedz

2

„Wygląda na to, że podejście pythonowy jest zrobić większość rzeczy jako własności”

To zależy, ale to jest blisko.

"Gdybym to zakodowane w PHP lub Java, ja prawdopodobnie wybrały do ​​tworzenia metod getter/setter ..."

dobre. To wystarczająco Pythonicznie. Twoje funkcje gettera i ustawiającego są powiązane w obrębie właściwości; to całkiem dobrze.

Na czym polega pytanie?

Pytasz, jak przeliterować: property?

Jednak "przejrzyste sprawdzanie poprawności" - jeśli dobrze odczytam przykładowy kod - może nie być tak dobrym pomysłem.

Twój model i zatwierdzenie powinny być prawdopodobnie przechowywane osobno. Często ma wiele walidacji dla jednego modelu. Dla niektórych użytkowników pola są opcjonalne, stałe lub nieużywane; to prowadzi do wielu walidacji.

Będziesz szczęśliwszy podążając za wzorcem projektowym Django używania Form do sprawdzania poprawności, niezależnie od modelu.

+2

Nie jestem pewien, jaki rodzaj magii SQLAlchemy wykorzystuje wiążą się właściwości klasy modelu. Nie założyłbym, że można bezpiecznie zdefiniować własną 'mac = property()' na mojej klasie. Myślę, że moje pytanie jest bezpieczne? Jeśli tak, to czy są jakieś gotcha? Jeśli nie, jakie są inne alternatywy? –

+0

Nie ma magii. To nie są gotchas. Alternatywą jest to, co zwykle robimy: przeprowadzamy walidację * poza * klasą modelu, co jeszcze bardziej upraszcza. Zdefiniuj swoją walidację * poza * modelem, a następnie nie musisz się o to martwić. –

7

Tak. Można to zrobić ładnie za pomocą MapperExtension.

# uses sqlalchemy hooks to data model class specific validators before update and insert 
class ValidationExtension(sqlalchemy.orm.interfaces.MapperExtension): 
    def before_update(self, mapper, connection, instance): 
     """not every instance here is actually updated to the db, see http://www.sqlalchemy.org/docs/reference/orm/interfaces.html?highlight=mapperextension#sqlalchemy.orm.interfaces.MapperExtension.before_update""" 
     instance.validate() 
     return sqlalchemy.orm.interfaces.MapperExtension.before_update(self, mapper, connection, instance) 
    def before_insert(self, mapper, connection, instance): 
     instance.validate() 
     return sqlalchemy.orm.interfaces.MapperExtension.before_insert(self, mapper, connection, instance) 


sqlalchemy.orm.mapper(model, table, extension = ValidationExtension(), **mapper_args) 

Możesz sprawdzić before_update odniesienie bo nie każdy przypadek jest tu rzeczywiście zaktualizowany do db.

13

Możesz dodać walidację danych w swoich klasach SQLAlchemy przy użyciu dekoratora @validates().

Od docs - Simple Validators:

walidator atrybut może podnieść wyjątek, zatrzymując proces mutowania wartość atrybutu, lub może zmienić daną wartość na coś innego.

from sqlalchemy.orm import validates 

class EmailAddress(Base): 
    __tablename__ = 'address' 

    id = Column(Integer, primary_key=True) 
    email = Column(String) 

    @validates('email') 
    def validate_email(self, key, address): 
     # you can use assertions, such as 
     # assert '@' in address 
     # or raise an exception: 
     if '@' not in address: 
      raise ValueError('Email address must contain an @ sign.') 
     return address 
+0

Po prostu szybkie pytanie: czy chcę prostej walidacji "obecności", czy powinienem dodać 'nullable = false' do deklaracji kolumny, a następnie spróbować złapać błędy' session.commit() '? Czy powinienem spróbować podobnego walidatora? Dzięki. –

Powiązane problemy