SQLAlchemy पंक्ति प्रविष्टि कैसे अपडेट करें?


138

तालिका मान लें तीन स्तंभ हैं: username, passwordऔर no_of_logins

जब उपयोगकर्ता लॉगिन करने की कोशिश करता है, तो यह एक क्वेरी के साथ प्रविष्टि के लिए जाँच की जाती है जैसे

user = User.query.filter_by(username=form.username.data).first()

यदि पासवर्ड मेल खाता है, तो वह आगे बढ़ता है। मैं जो करना चाहता हूं वह यह है कि उपयोगकर्ता कितनी बार लॉग इन करता है। इस प्रकार जब भी वह सफलतापूर्वक लॉग इन करता है, तो मैं no_of_loginsफ़ील्ड को बढ़ाना चाहता हूं और इसे उपयोगकर्ता तालिका में वापस संग्रहीत करना चाहता हूं । मुझे यकीन नहीं है कि SqlAlchemy के साथ अपडेट क्वेरी कैसे चला सकता हूं।

जवाबों:


132
user.no_of_logins += 1
session.commit()

12
stackoverflow.com/a/2334917/125507 का कहना है कि यह इसे करने का एक बुरा तरीका है। इसके अलावा क्या होगा अगर पंक्ति अभी तक मौजूद नहीं है?
एंडोलिथ

6
एंडोलिथ के लिंक के अनुसार, user.no_of_logins += 1दौड़ की स्थिति बना सकते हैं। इसके बजाय उपयोग करें user.no_of_logins = user.no_of_logins + 1। एसक्यूएल में अनुवादित बाद का सही तरीका बन जाता है SET no_of_logins = no_of_logins + 1:।
चैमग

5
@ChaimG मुझे लगता है कि आप का मतलब है user.no_of_logins = User.no_of_logins + 1, या दूसरे शब्दों में SQL अभिव्यक्ति का उत्पादन करने के लिए मॉडल के साधन विशेषता का उपयोग करें। जैसा कि आपकी टिप्पणी है कि एक ही दौड़ की स्थिति उत्पन्न करने के 2 तरीके प्रदर्शित होते हैं।
इलाजा एवरिल डे

2
वो नहीं हैं। पूर्व एक एसक्यूएल अभिव्यक्ति के लिए विशेषता सेट करता है, बाद वाला पायथन में इन-प्लेस जोड़ देता है और फिर से दौड़ का परिचय देता है।
इलजा एवरिल

1
@ Ajrizzo मैं उस सीरियल ट्रांजेक्शन आइसोलेशन-लेवल से परिचित नहीं हूं, लेकिन मेरी समझ से यह पायथन में इन-प्लेस जोड़ के साथ प्रदर्शन करने की अनुमति देता है। यदि कोई दौड़ है, तो लेन-देन में से एक तब सफल होगा और अन्य विफल हो जाएंगे और फिर से प्रयास करना होगा (डीबी के नए राज्य के साथ)। लेकिन मुझे गलत समझा जा सकता है।
इल्जा एवरिल

343

UPDATEउपयोग करने के कई तरीके हैंsqlalchemy

1) user.no_of_logins += 1
   session.commit()

2) session.query().\
       filter(User.username == form.username.data).\
       update({"no_of_logins": (User.no_of_logins +1)})
   session.commit()

3) conn = engine.connect()
   stmt = User.update().\
       values(no_of_logins=(User.no_of_logins + 1)).\
       where(User.username == form.username.data)
   conn.execute(stmt)

4) setattr(user, 'no_of_logins', user.no_of_logins+1)
   session.commit()

3
मैं setattr(query_result, key, value)कुछ अपडेट के लिए फ्लास्क SQLAlchemy में कमिट के बाद उपयोग करता हूं । इस पैटर्न को छूट देने का कोई कारण?
मार्क

2
@ दत्तामाफिया: आप उपयोग कर सकते हैं setattr(query_result, key, value), जो लिखने के बिल्कुल बराबर हैquery_result.key = value
निमा सोरोश

Thx @NimaSoroush, यही मैं करता हूँ और हाँ समकक्ष।
मार्क

8
क्या इन मामलों के बीच अंतर की व्याख्या करना संभव है? धन्यवाद!
हत्शेपसट

1
@Hatshepsut एक अंतर जो मुझे आज 4 और 1/2 के बीच आया है वह है: group.google.com/forum/@topic/sqlalchemy/wGUuAy27otM
विकास प्रसाद

13

स्वीकृत उत्तर की टिप्पणियों में महत्वपूर्ण मुद्दे को स्पष्ट करने के लिए उदाहरण

मैं इसे तब तक नहीं समझ पाया जब तक मैं खुद इसके साथ नहीं खेलता, इसलिए मुझे लगा कि अन्य लोग भी होंगे जो भ्रमित थे। कहते हैं कि आप उस उपयोगकर्ता पर काम कर रहे हैं id == 6जिसकी no_of_logins == 30शुरुआत कब और किससे हुई थी।

# 1 (bad)
user.no_of_logins += 1
# result: UPDATE user SET no_of_logins = 31 WHERE user.id = 6

# 2 (bad)
user.no_of_logins = user.no_of_logins + 1
# result: UPDATE user SET no_of_logins = 31 WHERE user.id = 6

# 3 (bad)
setattr(user, 'no_of_logins', user.no_of_logins + 1)
# result: UPDATE user SET no_of_logins = 31 WHERE user.id = 6

# 4 (ok)
user.no_of_logins = User.no_of_logins + 1
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6

# 5 (ok)
setattr(user, 'no_of_logins', User.no_of_logins + 1)
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6

बिंदु

उदाहरण के बजाय कक्षा को संदर्भित करके, आप SQLAlchemy को वेतन वृद्धि के बारे में होशियार होने के लिए प्राप्त कर सकते हैं, यह पायथन पक्ष के बजाय डेटाबेस की तरफ से हो सकता है। डेटाबेस में इसे करना बेहतर है क्योंकि यह डेटा भ्रष्टाचार के लिए कम असुरक्षित है (उदाहरण के लिए दो क्लाइंट एक ही समय में दो के बजाय केवल एक वेतन वृद्धि के शुद्ध परिणाम के साथ वेतन वृद्धि का प्रयास करते हैं)। अगर आप ताले लगाते हैं या अलगाव के स्तर से टकराते हैं तो मुझे लगता है कि पायथन में इंक्रीमेंट करना संभव है, लेकिन अगर आपके पास नहीं है तो परेशान क्यों हों?

एक चेतावनी

यदि आप एसक्यूएल का उत्पादन करने वाले कोड के माध्यम से दो बार वेतन वृद्धि करने जा रहे हैं SET no_of_logins = no_of_logins + 1, तो आपको वेतन वृद्धि के बीच कम से कम फ्लश करने की आवश्यकता होगी, अन्यथा आपको केवल एक वेतन वृद्धि मिलेगी:

# 6 (bad)
user.no_of_logins = User.no_of_logins + 1
user.no_of_logins = User.no_of_logins + 1
session.commit()
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6

# 7 (ok)
user.no_of_logins = User.no_of_logins + 1
session.flush()
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6
user.no_of_logins = User.no_of_logins + 1
session.commit()
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6

हैलो, आपके उत्तर के लिए धन्यवाद, एक अंतर चर के बजाय मैं एक स्ट्रिंग चर को अपडेट करने की कोशिश कर रहा हूं, मैं यह कैसे कर सकता हूं? मैं एक sqlite डेटाबेस का उपयोग कर रहा हूं और जिन चरों को बदलना चाहता हूं, वे current_user में हैं, एक फॉर्म सबमिट करने के माध्यम से
dani bilel

1
@danibilel प्रलेखन की जाँच करें, जो पूरी तरह से है। ट्यूटोरियल का यह हिस्सा स्ट्रिंग फ़ील्ड्स को अद्यतन करने पर चला जाता है: docs.sqlalchemy.org/en/13/orm/… । अन्यथा, मेरा सुझाव है कि आप एक नया प्रश्न पोस्ट करें जो आपको विशेष रूप से अटक गया है।
मैरेडेशे

इस लिंक के लिए धन्यवाद, जब मैंने पूरा दिन खोज में बिताया, तो मुझे पता है कि मेरी समस्या db.session.commit () के साथ है, यह कंसोल में परिवर्तनों को जारी नहीं रखता है, जैसा कि मुझे करना चाहिए, मुझे ऐसे ही सवाल मिले, लेकिन जवाब नहीं मिला। मेरे लिए काम करते हैं, वास्तविक वेब ऐप में यह और भी बुरा है! परिवर्तनों को बिल्कुल भी सहेजा नहीं जाता है, लंबी टिप्पणी के लिए खेद है लेकिन मैं वेबसाइट की नीति के कारण कोई सवाल नहीं जोड़ सकता, किसी भी मदद की सराहना की जाएगी।
दानी बाइल

4

user=User.query.filter_by(username=form.username.data).first()कथन की सहायता से आपको userवेरिएबल में निर्दिष्ट उपयोगकर्ता मिलेगा ।

अब आप नए ऑब्जेक्ट वैरिएबल के मान को बदल सकते हैं user.no_of_logins += 1और परिवर्तनों को session's कमिट विधि' के साथ सहेज सकते हैं ।


2

मैंने टेलीग्राम बॉट लिखा, और अद्यतन पंक्तियों के साथ कुछ समस्या है। यदि आपके पास मॉडल है, तो इस उदाहरण का उपयोग करें

def update_state(chat_id, state):
    try:
        value = Users.query.filter(Users.chat_id == str(chat_id)).first()
        value.state = str(state)
        db.session.flush()
        db.session.commit()
        #db.session.close()
    except:
        print('Error in def update_state')

क्यों उपयोग करें db.session.flush()? इसीलिए >>> SQLAlchemy: फ्लश () और कमिट () के बीच क्या अंतर है?


7
फ्लश प्रतिबद्ध से पहले पूरी तरह से बेमानी है। एक प्रतिबद्धता हमेशा स्पष्ट रूप से फ्लश होती है। जैसा कि Q / A में कहा गया है: " flush()हमेशा एक कॉल के भाग के रूप में कहा जाता है commit()"
Ilja Everilä
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.