sqlalchemy फ्लश () और आईडी डालें?


114

मैं कुछ इस तरह करना चाहता हूं:

f = Foo(bar='x')
session.add(f)
session.flush()

# do additional queries using f.id before commit()
print f.id # should be not None

session.commit()

लेकिन f.idहै Noneजब मैं यह प्रयास करें। में इससे कैसे चला सकता हूँ?


2
क्या आप SA इंजन को इनिशियलाइज़ कर सकते हैं echo=Trueऔर देख सकते हैं कि SQL फ्लश-टाइम पर क्या निष्पादित करता है? आप जो वर्णन करते हैं वह काम करना चाहिए और आपको आईडी देना चाहिए , लेकिन हो सकता है कि कोई और मुद्दा हो जिसके परिणामस्वरूप f.id कोई नहीं हो।
पावेल रेपिन

जवाबों:


63

आपके सैंपल कोड को वैसे ही काम करना चाहिए जैसा वह है। SQLAlchemy के लिए एक मूल्य प्रदान किया जाना चाहिए f.id, इसके प्राथमिक-कुंजी कॉलम को ऑटोजेनरेट करना। प्राथमिक-प्रमुख विशेषताएँ flush()प्रक्रिया के भीतर तुरंत उत्पन्न हो जाती हैं क्योंकि वे उत्पन्न होती हैं, और किसी भी कॉल की commit()आवश्यकता नहीं होनी चाहिए। तो यहाँ उत्तर एक या एक से अधिक में निहित है:

  1. आपके मानचित्रण का विवरण
  2. यदि उपयोग में बैकएंड की कोई विषम विचित्रताएँ हैं (जैसे कि, SQLite समग्र प्राथमिक कुंजी के लिए पूर्णांक मान उत्पन्न नहीं करता है)
  3. जब आप इको चालू करते हैं तो उत्सर्जित SQL क्या कहता है

1
आप सही हैं, शेल में एक त्वरित जांच से पता चलता है कि यह मूल्य के साथ प्राथमिक कुंजी फ़ील्ड को पॉप्युलेट करता है। मुझे जांच करनी होगी कि यह व्यवहार में क्यों नहीं चल रहा था।
एल्फ

3
"आपका नमूना कोड एक मूल्य प्रदान करना चाहिए" जैसे आप कह रहे हैं "आपको पहली बार आईडी के लिए एक मूल्य देना चाहिए था", बजाय "उस कोड के जो आपको काम करना चाहिए था"। यह मेरे लिए स्पष्ट हो गया कि आप तीसरे पढ़ने के बाद पूर्व की बजाय उत्तरार्द्ध थे। क्या आप स्पष्ट कर सकते हैं?
स्टोकेस्टिक

126

मैं बस एक ही समस्या को लेकर चला हूं, और परीक्षण के बाद मैंने पाया है कि इन उत्तरों में से कोई भी पर्याप्त नहीं है।

वर्तमान में, या sqlalchemy .6+ के रूप में, एक बहुत ही सरल उपाय है (मुझे नहीं पता कि यह पूर्व संस्करण में मौजूद है, हालांकि मुझे लगता है कि यह करता है)

session.refresh ()

तो, आपका कोड कुछ इस तरह दिखाई देगा:

f = Foo(bar=x)
session.add(f)
session.flush()
# At this point, the object f has been pushed to the DB, 
# and has been automatically assigned a unique primary key id

f.id
# is None

session.refresh(f)
# refresh updates given object in the session with its state in the DB
# (and can also only refresh certain attributes - search for documentation)

f.id
# is the automatically assigned primary key ID given in the database.

यह कैसे करना है।


8
यह एक उत्तर के करीब हो रहा है जो मेरे लिए काम कर सकता है लेकिन मुझे निम्नलिखित त्रुटि प्राप्त होती है: InvalidRequestError: '<....>' उदाहरण ताज़ा नहीं कर सका। यह फ्लश के बाद दिखाई देता है कि उदाहरण केवल अब मौजूद नहीं है। किसी भी अंतर्दृष्टि की सराहना करें।
प्लेडफ़ैन

1
तुमने तो मेरी गांड ही बचा ली। मुझे नहीं लगता कि मैं कभी भी DjMO से आने वाले ORM का उपयोग करूंगा। फ्लश () कमांड IMHO के रूप में काम नहीं करता है।
मार्क

2
अद्यतन, मुझे उपयोग करना था sessionmaker(autoflush=True), कि कॉम्बो w / ताज़ा () ने मुझे पंक्ति आईडी प्रदान की। #grrr
मार्क '

5
तुम न के बीच अंतर को समझते हैं flush()और commit():, यहाँ एक अच्छा व्याख्या दी गई है stackoverflow.com/a/4202016/1252290
Epoc

2
@PlaidFan flush()उपयोग के बजाय commit()और उसके ठीक बाद - इसे ताज़ा करें session.refresh(f), मेरे लिए काम करता है, और मैं SQLAlchemy संस्करण का उपयोग करता हूं0.6.7
रिकी लेवी

20

सभी के लिए धन्यवाद। मैंने कॉलम मैपिंग को संशोधित करके अपनी समस्या हल की। मेरे लिए, autoincrement=Trueआवश्यक है।

मूल:

id = Column('ID', Integer, primary_key=True, nullable=False)

संशोधित होने के बाद:

id = Column('ID', Integer, primary_key=True, autoincrement=True, nullable=True)

फिर

session.flush()  
print(f.id)

ठीक है!


6

डीपीबी द्वारा दिए गए उत्तर के विपरीत, एक ताज़ा आवश्यक नहीं है। एक बार जब आप फ्लश करते हैं, तो आप आईडी फ़ील्ड का उपयोग कर सकते हैं, sqlalchemy स्वचालित रूप से आईडी को रीफ्रेश करता है जो बैकएंड पर उत्पन्न होता है।

मैंने इस समस्या का सामना किया और कुछ जांच के बाद सटीक कारण का अनुमान लगाया, मेरा मॉडल आईडी के साथ पूर्णांक के रूप में बनाया गया था और मेरे रूप में आईडी को हिडनफील्ड के साथ दर्शाया गया था (क्योंकि मैं अपने फॉर्म में आईडी नहीं दिखाना चाहता था)। छिपे हुए फ़ील्ड को टेक्स्ट के रूप में डिफ़ॉल्ट रूप से दर्शाया जाता है। एक बार जब मैंने विजेट के साथ पूर्णांक को रूप में बदल दिया = हिडन इनपुट ()) समस्या हल हो गई।


1
जैसा कि केवल ताज़ा कहा गया है () मेरे लिए काम किया। एक डेटा माइग्रेशन करने में मुझे FK को पॉप्युलेट करने के लिए एक पंक्ति में पंक्ति ID की आवश्यकता होती है। मैंने कमिट, फ्लश, सेशन हैकिंग और रिफ्रेश () के हर कॉम्बो को आजमाया जो काम कर गया। मेरा डेटा सुपर क्लीन है और मुझे सिर्फ यह पता चल रहा है कि एसक्यूए वास्तव में अच्छा नहीं है (कम से कम 5 प्रमुख ORMS में काफी एक्सपोज हो रहा है)। एक ऐड () -> कमिट () / फ्लश () के लिए पंक्ति आईडी प्राप्त करने की कोशिश कर रहे 5+ घंटे पर बस रैप करना।
मार्क

1

मुझे एक बार 0कॉल session.addकरने की विधि से पहले आईडी को असाइन करने में समस्या थी । आईडी को डेटाबेस द्वारा सही ढंग से असाइन किया गया था लेकिन सही आईडी को सत्र के बाद से पुनर्प्राप्त नहीं किया गया था session.flush()


-7

आपको session.save_or_update(f)इसके बजाय उपयोग करने का प्रयास करना चाहिए session.add(f)


1
save_or_update0.5 या तो के बाद से पदावनत किया गया है। session.add()करना चाहिए।
पावेल रेपिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.