2012-12-25 14 views
8

की स्थापना मैं एक वर्ग है:SQLAlchemy अद्यतन ForeignKey जब रिश्ता

class ExampleClass(Base): 
    __tablename__ = 'chart' 
    id = Column(Integer, primary_key=True) 
    element_id = Column(Integer, ForeignKey('anotherTable.id')) 
    element = relationship(AnotherClass) 
    element2_id = Column(Integer, ForeignKey('anotherTable2.id')) 
    element2 = relationship(AnotherClass2) 

मैं element_id और element2_id के आधार पर एक देखने क्या करना चाहते हैं:

class ExampleClass(Base): 
    ... 
    def get_with_element2(self, element2): 
     return session.query(ExampleClass).\ 
         filter_by(element_id = self.element_id, 
           element2_id = element2.id).first() 

समस्या मुझे लगता है कि अगर मैं एक नया ExampleClass ऑब्जेक्ट को तुरंत चालू करता हूं और इसे element असाइन करता हूं, element_id फ़ील्ड सेट नहीं किया जा रहा है:

a = ExampleClass(element=element_obj) 
a.element_id => None 

मैं इसे कैसे हल कर सकता हूं? इस तरह की स्थिति से निपटने का सबसे अच्छा तरीका क्या है?

उत्तर

9

सबसे पहले, नीचे दिए गए सभी उदाहरण मानते हैं कि ExampleClass उदाहरण कम से कम pending स्थिति में है यदि "लगातार" स्थिति (यानी session.add(a)) नहीं है। दूसरे शब्दों में, यदि आप अभी तक Session से इंटरैक्ट नहीं कर रहे हैं और ExampleClass ऑब्जेक्ट को एक में नहीं जोड़ा है, तो आपको relationship() का डेटाबेस-स्तरीय व्यवहार नहीं मिलेगा, जिसमें से विदेशी कुंजी कॉलम मान प्राथमिक हैं सुविधा। आप निश्चित रूप से इस काम के लिए सीधे करने के लिए स्वतंत्र हैं:

a = ExampleClass(element_id=element_obj.id) 

लेकिन यह स्पष्ट रूप से relationship() निर्माण द्वारा प्रदान की स्वचालन का इस्तेमाल कर रही है।

relationship() द्वारा विदेशी प्रमुख विशेषताओं का काम एक flush है, जो एक प्रक्रिया है कि केवल तब होता है जब डेटाबेस के साथ बातचीत में इस तरह के अपने लेन-देन session.commit() का उपयोग कर पूरा इससे पहले कि आप किसी SQL बयान session.query() का उपयोग कर फेंकना के रूप में या आप से पहले आवश्यक है, है के दौरान होता है ।

आम तौर पर, relationship() का दर्शन यह है कि आप केवल "तत्व" और "तत्व 2" विशेषताओं के साथ सौदा करेंगे, और दृश्यों के पीछे विदेशी कुंजी विशेषताओं को संभालने दें। आप इस तरह आपकी क्वेरी लिख सकते हैं:

session.query(ExampleClass).\ 
    filter_by(element=self.element).\ 
    filter_by(element2=element2) 

ORM SomeClass.somerelationship=someobject के रूप में एक तुलना में इस तरह लेने के लिए और कन्वर्ट कि विदेशी कुंजी अभिव्यक्ति SomeClass.some_fk=some_id में होगा, लेकिन अंतर यह है कि "some_id" का अंतिम मूल्य का मूल्यांकन क्वेरी को निष्पादित करने से ठीक पहले स्थगित है। इससे पहले कि क्वेरी निष्पादित किया जाता है, Query() वस्तु Session करने के लिए "autoflush" है, जो अपने ExampleClass पंक्ति के प्रभाव element_obj की प्राथमिक कुंजी पहचानकर्ता ExampleClass वस्तु पर element_id विशेषता करने के लिए आवंटित किया जा रहा के साथ डाला जा रहा होगा बताता है।

जबकि अभी भी का उपयोग कर FK इस तरह जिम्मेदार बताते हैं यदि आप एक समान प्रभाव हो सकता है, यह सिर्फ समझने के लिए कि यह कैसे काम करता है, हालांकि ज्यादातर है:

session.query(ExampleClass).\ 
    filter_by(element_id=bindparam(callable_=lambda: self.element_id)).\ 
    filter_by(element2_id=element2.id) 

या और भी अधिक स्पष्ट फ्लश पहले, कार्य करें:

session.flush() 
session.query(ExampleClass).\ 
    filter_by(element_id=self.element_id).\ 
    filter_by(element2_id=element2.id) 

तो डिग्री के लिए आप element_id जैसे विदेशी कुंजी विशेषताओं को संदर्भित करना चाहते हैं, आपको relationship() चीजों को स्पष्ट रूप से करने की भी आवश्यकता होगी।यदि आप ऑब्जेक्ट इंस्टेंस और relationship() -बाउंड विशेषता के साथ सख्ती से सौदा करते हैं, और autoflush सक्षम सामान्य डिफ़ॉल्ट छोड़ देते हैं, तो यह आमतौर पर "सही चीज़" करेगा और सुनिश्चित करेगा कि आवश्यकतानुसार गुण तैयार हो जाएं।

+0

स्पष्टीकरण के लिए बहुत बहुत धन्यवाद। मुझे नहीं पता था कि मैं खुद रिश्ते से फ़िल्टर कर सकता हूं और मैं चीजों को गड़बड़ नहीं करना चाहता था। तो निश्चित रूप से मैं इसे करने जा रहा हूं। –

संबंधित मुद्दे