Prima di tutto, tutti gli esempi seguenti presuppongono che l'istanza ExampleClass
sia almeno nello stato pending se non lo stato "persistente" (ovvero, session.add(a)
). In altre parole, se non si sta ancora interagendo con un e non si è aggiunto l'oggetto ExampleClass
a uno, non si otterrà alcuno dei comportamenti a livello di database di relationship()
, di cui il mantenimento dei valori di colonna chiave esterna è il principale caratteristica. Siete ovviamente liberi di fare questo compito direttamente:
a = ExampleClass(element_id=element_obj.id)
ma questo non è, ovviamente, facendo uso dell'automazione fornita dal relationship()
costrutto.
L'assegnazione di attributi chiave esterna da relationship()
si verifica nel corso di una flush, che è un processo che si verifica solo quando è necessaria l'interazione con il database, ad esempio prima si emettono un'istruzione SQL utilizzando session.query()
o prima di completare la transazione utilizzando session.commit()
.
In generale, la filosofia di relationship()
consiste nel fatto che si tratterebbe solo degli attributi "elemento" e "elemento2" qui e che gli attributi della chiave esterna vengano gestiti dietro le quinte. È possibile scrivere la query in questo modo:
session.query(ExampleClass).\
filter_by(element=self.element).\
filter_by(element2=element2)
L'ORM avrà un confronto, come SomeClass.somerelationship=someobject
e convertire che nell'espressione di chiave esterna SomeClass.some_fk=some_id
, ma la differenza è, la valutazione del valore finale di "some_id" è differita fino alla destra prima dell'esecuzione della query. Prima che la query venga eseguita, l'oggetto dice a "autoflush" Session
, che avrà l'effetto della riga ExampleClass
inserita insieme all'identificativo chiave primaria di element_obj
assegnato all'attributo element_id
sull'oggetto ExampleClass
.
si potrebbe ottenere un effetto simile, pur utilizzando l'FK attributi come questo, questo è per lo più solo per capire come funziona però:
session.query(ExampleClass).\
filter_by(element_id=bindparam(callable_=lambda: self.element_id)).\
filter_by(element2_id=element2.id)
o anche più esplicito, fare la prima ondata:
session.flush()
session.query(ExampleClass).\
filter_by(element_id=self.element_id).\
filter_by(element2_id=element2.id)
Quindi, nella misura in cui si desidera fare riferimento a attributi di chiave esterna come element_id
in modo esplicito, è necessario fare anche le cose che relationship()
fa esplicitamente per voi.Se gestisci rigorosamente le istanze dell'oggetto e l'attributo-relationship()
-bound e lascia le tipiche impostazioni predefinite come autoflush
abilitate, generalmente eseguirà la "cosa giusta" e assicurati che gli attributi siano pronti quando necessario.
Grazie mille per la spiegazione. Non sapevo se avrei potuto filtrare dalla relazione stessa e non volevo rovinare le cose. Quindi sicuramente questo è il modo in cui lo farò. –