2012-10-11 22 views
63

मैं एक TextField से अशक्त = सच निकालना चाहते लंबित है:दक्षिण: टेबल परिवर्तन नहीं कर सकते, क्योंकि यह ट्रिगर घटनाओं

- footer=models.TextField(null=True, blank=True) 
+ footer=models.TextField(blank=True, default='') 

मैं एक स्कीमा प्रवास बनाया:

manage.py schemamigration fooapp --auto 

के बाद से कुछ पाद लेख स्तंभ

django.db.utils.IntegrityError: column "footer" contains null values 

मैं स्कीमा प्रवास को यह कहा:: शून्य मैं यह त्रुटि अगर मैं माइग्रेशन चला पाने

for sender in orm['fooapp.EmailSender'].objects.filter(footer=None): 
     sender.footer='' 
     sender.save() 

अब मैं मिलता है:

django.db.utils.DatabaseError: cannot ALTER TABLE "fooapp_emailsender" because it has pending trigger events 

क्या गलत है?

+0

यह प्रश्न समान है: http://stackoverflow.com/questions/28429933/django-migrations-using-runpython-to-commit-changes और ऐसे उत्तर थे जो मेरे लिए अधिक उपयोगी थे। – SpoonMeiser

उत्तर

73

प्रत्येक माइग्रेशन एक लेनदेन के अंदर है। PostgreSQL में आपको तालिका को अपडेट नहीं करना चाहिए और फिर एक लेनदेन में तालिका स्कीमा को बदलना होगा।

आपको डेटा माइग्रेशन और स्कीमा माइग्रेशन को विभाजित करने की आवश्यकता है। सबसे पहले इस कोड के साथ डेटा स्थानांतरण बनाएँ:

for sender in orm['fooapp.EmailSender'].objects.filter(footer=None): 
    sender.footer='' 
    sender.save() 

फिर स्कीमा प्रवास बनाएँ:

manage.py schemamigration fooapp --auto 

अब आपके पास दो लेन-देन किया है और दो चरणों में पलायन काम करना चाहिए।

+5

पोस्टग्रेएसक्यूएल ने संभवतः इस तरह के लेनदेन के संबंध में अपना व्यवहार बदल दिया, क्योंकि मैंने सर्वर पर (डीटीजीआरएसक्यूएल 9.1) पर असफल होने पर मेरी dev मशीन (PostgreSQL 9.4) दोनों डेटा और स्कीमा परिवर्तनों के साथ माइग्रेशन चलाने में कामयाब रहा। –

11

अभी इस समस्या को हिट करें। स्कीमा परिवर्तन से डेटा परिवर्तन अलग करने के लिए आप स्कीमा माइग्रेशन में db.start_transaction() और db.commit_transaction() का भी उपयोग कर सकते हैं। शायद एक अलग डेटा माइग्रेशन के रूप में इतना साफ नहीं है, लेकिन मेरे मामले में मुझे स्कीमा, डेटा, और फिर एक और स्कीमा माइग्रेशन की आवश्यकता होगी, इसलिए मैंने इसे एक बार में करने का फैसला किया।

+5

इस समाधान के साथ समस्या यह है: क्या होता है यदि आपका माइग्रेशन db.commit_transaction() के बाद विफल रहता है? यदि आपको इसकी आवश्यकता है, तो मैं तीन माइग्रेशन का उपयोग करना पसंद करता हूं: स्कीमा-माइग, डेटा-माइग, स्कीमा-माइग। – guettli

+0

देखें: http://django.readthedocs.io/en/latest/ref/migration-operations.html डेटाबेस DDL लेनदेन (SQLite और PostgreSQL) का समर्थन है, RunPython संचालन के लेन-देन को स्वचालित रूप से के अलावा जुड़ा हुआ नहीं है कि पर प्रत्येक माइग्रेशन के लिए बनाए गए लेनदेन। इस प्रकार, PostgreSQL पर, उदाहरण के लिए, आपको उसी माइग्रेशन में स्कीमा परिवर्तन और रनपीथन ऑपरेशन को संयोजित करने से बचना चाहिए या आप ऑपरेशनल एरर जैसे त्रुटियों को दबा सकते हैं: तालिका "mytable" को नहीं बदल सकता क्योंकि इसमें ट्रिगर ईवेंट लंबित हैं। –

75

इसके लिए एक और कारण यह हो सकता है क्योंकि आप NOT NULL पर कॉलम सेट करने का प्रयास करते हैं, जब वास्तव में पहले से ही NULL मान होते हैं।

+1

यह बहुत बड़ा है! इसके लिए शुक्रिया। –

+2

इसका समाधान करने के लिए आप या तो डेटा माइग्रेशन या मैन्युअल रूप से (manage.py shell) का उपयोग कर सकते हैं और गैर-अनुरूप मानों को अपडेट कर सकते हैं – mgojohn

+0

@mgojohn आप यह कैसे करते हैं? – pyramidface