2012-09-30 13 views
83

मैं Django के साथ एक मेज अपडेट करना चाहते हैं - कच्चे एसक्यूएल में कुछ इस तरह:Django के साथ 'थोक अद्यतन' कैसे करें?

update tbl_name set name = 'foo' where name = 'bar' 

मेरा पहला परिणाम कुछ इस तरह है - लेकिन यह है कि बुरा है, है न?

list = ModelClass.objects.filter(name = 'bar') 
for obj in list: 
    obj.name = 'foo' 
    obj.save() 

क्या कोई और शानदार तरीका है?

+1

आप बैच डालने की तलाश में हो सकते हैं। Http://stackoverflow.com/questions/4294088/accelerate-bulk-insert-using-djangos-orm – Pramod

+0

पर एक नज़र डालें, मैं नया डेटा डालना पसंद नहीं करता - बस मौजूदा अपडेट करें। – Thomas

+2

शायद select_for_update की मदद से? https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.select_for_update –

उत्तर

149

django दस्तावेज में update फ़ंक्शन का संदर्भ लें: https://docs.djangoproject.com/en/dev/ref/models/querysets/#update

संक्षेप में आप का उपयोग करने के लिए सक्षम होना चाहिए:

ModelClass.objects.filter(name='bar').update(name="foo") 

तुम भी F वस्तुओं का उपयोग कर सकते incrementing पंक्तियों की तरह काम करने के लिए:

from django.db.models import F 
Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1) 

दस्तावेज़ देखें: https://docs.djangoproject.com/en/1.9/topics/db/queries/

हालांकि , ध्यान दें कि:

  • यह ModelClass.save विधि का उपयोग नहीं करेगा (इसलिए यदि आपके अंदर कुछ तर्क है तो ट्रिगर नहीं किया जाएगा)।
  • कोई django सिग्नल उत्सर्जित नहीं किया जाएगा।
+21

यह भी ध्यान दें कि 'save()', 'DateTimeField' फ़ील्ड्स का उपयोग न करने के परिणामस्वरूप 'auto_now = True' (" संशोधित "कॉलम) अपडेट नहीं होंगे। – Arthur

+2

लेकिन 'ModelClass.objects.filter (name = 'bar')। अद्यतन (name =" foo ") थोक अद्यतन के उद्देश्य को पूरा नहीं करता है, अगर मेरे पास अलग-अलग आईडी के लिए अलग-अलग डेटा हैं तो मैं लूप का उपयोग किए बिना ऐसा कैसे कर सकता हूं ? – Shashank

+0

@shihon मुझे यकीन नहीं है कि मैं आपको सही मिला लेकिन मैंने जवाब में उदाहरण जोड़ा। –

24

django-bulk-updatehere on GitHub का उपयोग करने पर विचार करें।

स्थापित करें: pip install django-bulk-update

लागू: (परियोजनाओं रीडमी फ़ाइल से सीधे ले जाया कोड)

from bulk_update.helper import bulk_update 

random_names = ['Walter', 'The Dude', 'Donny', 'Jesus'] 
people = Person.objects.all() 

for person in people: 
    r = random.randrange(4) 
    person.name = random_names[r] 

bulk_update(people) # updates all columns using the default db 

अद्यतन: मार्क टिप्पणियाँ इस पर पंक्तियों के हजारों को अद्यतन करने के लिए उपयुक्त नहीं है में बताते हैं के रूप में एक बार। हालांकि यह छोटे बैचों के लिए 10 से 100 के लिए उपयुक्त है। आपके लिए सही बैच का आकार आपके सीपीयू और क्वेरी जटिलता पर निर्भर करता है। यह उपकरण एक डंप ट्रक की तुलना में एक व्हील बैरो की तरह है।

+5

मैंने django-bulk-update की कोशिश की, और मैं व्यक्तिगत रूप से इसका उपयोग करके हतोत्साहित करता हूं। यह आंतरिक रूप से एक एकल SQL कथन बनाने के लिए है जो इस तरह दिखता है: अद्यतन "तालिका" सेट "फ़ील्ड" = केस "आईडी" जब% s THEN% s WHEN% s THEN% s [...] जहां आईडी (% s,% s, [...]);यह कुछ पंक्तियों के लिए बिल्कुल सही है (जब थोक अद्यतनकर्ता की आवश्यकता नहीं होती है), लेकिन 10,000 के साथ, क्वेरी इतनी जटिल है कि पोस्टग्रेस डिस्क पर लिखने के समय से 100% क्वेरी को समझने के साथ सीपीयू के साथ अधिक समय बिताता है । –

+0

@MarcGarcia अच्छा बिंदु। मैंने पाया कि कई डेवलपर्स बाहरी प्रभावों का उपयोग किए बिना बाहरी पुस्तकालयों का उपयोग करते हैं – Dejell

+2

@MarcGarcia मैं असहमत हूं कि थोक अद्यतन मूल्यवान नहीं है और केवल हजारों अपडेट आवश्यक होने पर ही वास्तव में आवश्यक है। एक बार में 10,000 पंक्तियों को करने के लिए इसका उपयोग करने के कारणों के लिए सलाह नहीं दी जाती है, लेकिन 50 पंक्तियों को अद्यतन करने के लिए इसका उपयोग करके 50 अलग-अलग अद्यतन अनुरोधों के साथ डीबी को मारने से कहीं अधिक कुशल होता है। –

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