2009-06-24 6 views
1

Ich habe eine einfache "Rechnungen" -Klasse mit einem "Number" -Attribut, das von der Anwendung zugewiesen werden muss, wenn der Benutzer eine Rechnung speichert. Es sind einige Einschränkungen:Automatisch inkrementieren Attribut mit benutzerdefinierter Logik in SQLAlchemy

1) die Anwendung ein (dünner) Client-Server ein, so was auch immer ordnet die Zahl für Kollisionen
2) Rechnungen achten muss eine „Version“ hat zuschreiben, so dass ich kann kein einfaches DBMS-Level-Autoinkrementierungsfeld verwenden

Ich versuche, dies mit einem benutzerdefinierten Typ zu erstellen, der in jeder Zeit treten würde, die eine Rechnung gespeichert wird. Wenn process_bind_param mit einen None-Wert aufgerufen wird, wird ein Singleton irgendeiner Art aufgerufen, um die -Nummer zu ermitteln und Kollisionen zu vermeiden. Ist das eine anständige Lösung? Hier ist meine Wünsch Art Wie dem auch sei, ich bin .. ein Problem mit:

class AutoIncrement(types.TypeDecorator): 
    impl = types.Unicode 

    def copy(self): 
     return AutoIncrement() 

    def process_bind_param(self, value, dialect): 
     if not value: 
      # Must find next autoincrement value 
      value = "1" # Test value :) 
     return value 

Mein Problem jetzt ist, dass, wenn ich sparen eine Rechnung und AutoIncrement Sets „1“ als Wert für die Nummer, die Rechnung Instanz nicht bekommen aktualisiert mit der neuen Nummer .. Wird das erwartet? Fehle ich etwas? Vielen Dank für Ihre Zeit!

(SQLA 0.5.3 auf Python 2.6, mit postgreSQL 8,3)

Edit: Michael Bayer hat mir gesagt, dass dieses Verhalten zu erwarten ist, da TypeDecorators nicht mit Standardwerten beschäftigen.

Antwort

3

Gibt es einen bestimmten Grund, warum Sie nicht einfach einen default= Parameter in Ihrer Spaltendefinition verwenden? (Dies kann eine beliebige Python-Callable sein).

def generate_invoice_number(): 
    # special logic to generate a unique invoice number 

class Invoice(DeclarativeBase): 
    __tablename__ = 'invoice' 
    number = Column(Integer, unique=True, default=generate_invoice_number) 
    ... 
+0

Aua wusste nicht, dass Sie eine Callable dort verwenden können, danke! Ich werde es sofort versuchen :) – Joril

+0

Sagen Sie Ihre Standard-Callable gibt das Maximum der Spalte in der DB plus eins. Gibt es eine Möglichkeit zu behaupten, dass es keine Wettlaufbedingungen gibt, ohne sich darauf zu verlassen, dass ein Fehler in der Spalte eindeutig ist? –

+0

In diesem Fall ist es besser, wenn Sie Ihren Standard als Inline-SQL-Ausdruck schreiben. Dies wird ausführlich in der SQLAlchemy-Dokumentation unter http://www.sqlalchemy.org/docs/05/metadata.html#pre-executed-and-inline-sql-expressions beschrieben. –