2015-03-05 20 views
12

अगर मैं गैर-व्यर्थ मॉडल क्षेत्र है, इसे हटाने, और एक प्रवास बनाते हैं तो वह प्रवास गैर-परिवर्तनीय हो जाता है:रिवर्ट Django 1.7 RemoveField प्रवास

निम्नलिखित मॉडल पर विचार करें:

class Foo(models.Model): 
    bar = models.TextField() 
    test = models.TextField() # This field is to go away, bye-bye! 

और माइग्रेशन:

$ src/manage.py migrate app 0002 
Operations to perform: 
    Target specific migration: 0002_foo_test, from app 
Running migrations: 
    Unapplying app.0003_remove_foo_test...Traceback (most recent call last): 
... 
django.db.utils.IntegrityError: column "test" contains null values 
:

# app/migrations/003_remove_foo_test.py 

class Migration(migrations.Migration): 

    dependencies = [ 
     ('app', '0002_foo_test'), 
    ] 

    operations = [ 
     migrations.RemoveField(
      model_name='foo', 
      name='test', 
     ), 
    ] 

इस प्रवास Unapplying एक अपवाद फेंकता बेशक

, इस अपेक्षित व्यवहार है, यह clearly documented है और मुझे नहीं पूछ रहा हूँ कि ऐसा क्यों होता:

याद रखिए कि जब उलट यह वास्तव में एक मॉडल के लिए एक क्षेत्र को जोड़ने की है, यदि फ़ील्ड शून्य नहीं है तो यह इस ऑपरेशन को अपरिवर्तनीय बना सकता है (किसी भी डेटा हानि के अलावा, जो निश्चित रूप से अपरिवर्तनीय है)।

हालांकि, हम सब गलती करते हैं और कभी-कभी हम सिर्फ किसी भी तरहकी जरूरत एक क्षेत्र विलोपन रिवर्स, कि भले ही मैन्युअल रूप से सभी उलट गैर-शून्य क्षेत्रों के लिए एक तदर्थ ठूंठ मूल्य प्रदान करने का मतलब है। उदाहरण के लिए, दक्षिण माइग्रेशन वैकल्पिक रूप से ऐसे परिचालनों के उलटा होने की अनुमति देता है (डेवलपर से यह पूछकर कि पुनर्स्थापित क्षेत्रों के लिए डिफ़ॉल्ट प्रदान करना है या रिवर्स माइग्रेशन को अस्वीकार करना है), जो कि सभी नए फैंसी Django 1.7 माइग्रेशन के मामले में प्रतीत नहीं होता है ।

प्रश्न: Django 1.7+ माइग्रेशन के साथ फ़ील्ड हटाने को पूर्ववत करने का सबसे आसान/तेज़ तरीका क्या है (माना जाता है कि यह पहले से ही हुआ है)? मैन्युअल निर्देशों का एक सेट, पाइथन के साथ पूरी तरह से लिपि जाने की आवश्यकता नहीं है।

उत्तर

11

आप मैन्युअल रूप से एड कर सकते हैं यह आपके माइग्रेशन और को RemoveField से पहले फ़ील्ड के डिफ़ॉल्ट मान के साथ जोड़ें। माइग्रेशन लागू करने के बाद भी यह सुरक्षित होना चाहिए।इससे RemoveField होगा जो उलटा होने के बाद होगा।

एक उदाहरण। मॉडल summaryprofit नामित में होने वाले फ़ील्ड हटाने से पहले इस तरह परिभाषित किया गया था:

profit = models.PositiveIntegerField(verbose_name='profits') 

आप इसके बारे में RemoveField एक AlterField उस तरह से पहले जोड़ना चाहिए:

migrations.AlterField(
    model_name='summary', 
    name='profit', 
    field=models.PositiveIntegerField(verbose_name='profits', default=0), 
    preserve_default=False, 
    ), 
+0

'AlterField'' preserve_default' तर्क स्वीकार नहीं करता है (लेकिन ऐसा लगता है कि इस मामले में इसकी आवश्यकता नहीं है, क्योंकि 'डिफ़ॉल्ट' डेटाबेस स्कीमा के लिए अपना रास्ता नहीं मिलता है)। इसके अलावा, यह वास्तव में एक सही और इष्टतम समाधान प्रतीत होता है। धन्यवाद! –

+0

[दस्तावेज़ीकरण] के अनुसार (https://docs.djangoproject.com/en/1.7/ref/migration-operations/#django.db.migrations.operations.AlterField), हाँ यह करता है, लेकिन इसे 1.7 में जोड़ा गया था। 1। और उस स्थिति में, preserve_default कोई फर्क नहीं पड़ता। यह डेटाबेस के लिए अपना रास्ता मिलता है, लेकिन केवल थोड़ी देर के लिए। – GwynBleidD

+0

यह Django में काम नहीं करता है 1.8 – jess

3

यदि आप भविष्य में माइग्रेशन को उलट करने की कोशिश कर रहे हैं, तो आप फ़ील्ड को तीन माइग्रेशन के रूप में हटाने का प्रयास कर सकते हैं।

  1. क्षेत्र नल
  2. डेटा माइग्रेशन करें। आगे बढ़ो, कुछ मत करो। पीछे, नल को स्टब वैल्यू में कनवर्ट करें।
  3. क्षेत्र

इन तीन चरणों में से प्रत्येक निकालें प्रतिवर्ती होना चाहिए।

आप पहले से ही माइग्रेशन चला और यह रिवर्स करने की जरूरत है, तो आप

  1. मैन्युअल क्षेत्र जोड़ सकते हैं अनुमति देता है nulls
  2. एक ठूंठ मूल्य के लिए nulls परिवर्तित
  3. मैन्युअल रिक्त नहीं बाधा जोड़ने
  4. पिछले माइग्रेशन के लिए --fake साथ माइग्रेट
+0

मैं के बारे में काफी यकीन नहीं है "मैन्युअल रूप से जोड़ने फ़ील्ड "चरण 1 में। मैं निश्चित रूप से मैन्युअल रूप से चलने वाले टैबलेट से बचना चाहता हूं .. कॉलम जोड़ें, ओआरएम परत हमेशा यही करती है और हमेशा करना चाहिए। ओआरएम करता है (फ़ील्ड नामकरण, इंडेक्स प्रबंधित करना इत्यादि) की सभी छोटी सी चीजों को दोहराने के लिए प्रोग्रामर पर निर्भर नहीं है –

+0

मैन्युअल रूप से चल रहा एसक्यूएल आदर्श नहीं है, लेकिन कभी-कभी आपके पास कोई अन्य विकल्प नहीं हो सकता है। किसी और के पास एक बेहतर सुझाव हो सकता है। आप Django को './manage.py sqlmigrate --backwards' के साथ SQL उत्पन्न करने में सक्षम हो सकते हैं। – Alasdair

+0

मैं पुष्टि कर सकता हूं कि './manage.py sqlmigrate --backwards' इस माइग्रेशन को करने के लिए सही SQL देता है, और यदि आप PyCharm जैसे आईडीई का उपयोग कर रहे हैं तो यह चलाने में दर्दनाक नहीं है; माइग्रेशन-एडिटिंग दृष्टिकोण पीछे की ओर माइग्रेशन पर मेरे लिए काम नहीं करता था। – Symmetric

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