अंतिम प्रवास को वापस कैसे करें?


446

मैंने एक माइग्रेशन बनाया है, जिसमें एक नया टेबल जोड़ा गया है और एक नया माइग्रेशन बनाए बिना इसे वापस करना और माइग्रेशन हटाना चाहते हैं।

मैं यह कैसे करुं? क्या अंतिम माइग्रेशन को वापस करने का कोई आदेश है और फिर मैं केवल माइग्रेशन फ़ाइल को हटा सकता हूं?

जवाबों:


794

आप पिछले माइग्रेशन में माइग्रेट करके वापस लौट सकते हैं।

उदाहरण के लिए, यदि आपके अंतिम दो माइग्रेशन हैं:

  • 0010_previous_migration
  • 0011_migration_to_revert

तब आप करेंगे:

./manage.py migrate my_app 0010_previous_migration 

फिर आप माइग्रेशन हटा सकते हैं 0011_migration_to_revert

यदि आप Django 1.8+ का उपयोग कर रहे हैं, तो आप सभी माइग्रेशन के नाम दिखा सकते हैं

./manage.py showmigrations my_app

किसी ऐप के लिए सभी माइग्रेशन को रिवर्स करने के लिए, आप चला सकते हैं:

./manage.py migrate my_app zero

7
मैंने इस समस्या पर SO के कई उत्तर देखे हैं जो पुराने हैं और बस अब काम नहीं करते हैं। +1 क्योंकि यह Django 1.8 के साथ काम करता है।
एलनसे

2
कैसे हो अगर ऐप में केवल एक माइग्रेशन फ़ाइल / प्रारंभिक माइग्रेशन हो। और मुझे उस प्रारंभिक माइग्रेशन को पूर्ववत करने की आवश्यकता है?
अदियात मुबारक

37
migrateआदेश देना आप का उपयोग करें ./manage.py migrate my_app zeroअनुप्रयोग के लिए सभी माइग्रेशन unapply करने के लिए।
अलसादेयर

4
किसी कारण से, ./manage.py my_app 0010_prepret_migration मेरे लिए काम नहीं करता है। इसलिए मैंने उपयोग करने की कोशिश की ।/manage.py ने my_app 0010 माइग्रेट किया और यह काम कर गया। Django 1.8 पूरे माइग्रेशन नाम को क्यों नहीं लेगा?
वरुण वर्मा

4
जब तक आप अपने वास्तविक माइग्रेशन नाम का उपयोग कर रहे हैं, और नहीं '0010_previous_migration', मुझे नहीं पता कि आप उस व्यवहार को क्यों देखेंगे।
Alasdair

36

Alasdair द्वारा उत्तर मूल बातें शामिल हैं

  • उन माइग्रेशनों की पहचान करें जिन्हें आप चाहते हैं ./manage.py showmigrations
  • migrate ऐप नाम और माइग्रेशन नाम का उपयोग करना

लेकिन यह ध्यान दिया जाना चाहिए कि सभी माइग्रेशन उलट नहीं हो सकते हैं। यह तब होता है जब Django में उलटफेर करने का नियम नहीं है। अधिकांश परिवर्तनों के लिए, जिनके द्वारा आपने स्वचालित रूप से माइग्रेशन किए हैं ./manage.py makemigrations, उलट संभव होगा। हालाँकि, कस्टम स्क्रिप्ट के लिए आगे और पीछे दोनों तरह से लिखना होगा, जैसा कि यहाँ उदाहरण में बताया गया है:

https://docs.djangoproject.com/en/1.9/ref/migration-operations/

नो-ऑप रिवर्सल कैसे करें

यदि आपके पास एक RunPythonऑपरेशन था, तो शायद आप तार्किक रूप से कठोर उलट स्क्रिप्ट लिखने के बिना माइग्रेशन को वापस करना चाहते हैं। डॉक्स (लिंक से ऊपर) से उदाहरण के लिए निम्न त्वरित हैक यह अनुमति देता है, डेटाबेस को उसी स्थिति में छोड़ देता है कि यह माइग्रेशन लागू होने के बाद था, इसे उलटने के बाद भी।

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

def forwards_func(apps, schema_editor):
    # We get the model from the versioned app registry;
    # if we directly import it, it'll be the wrong version
    Country = apps.get_model("myapp", "Country")
    db_alias = schema_editor.connection.alias
    Country.objects.using(db_alias).bulk_create([
        Country(name="USA", code="us"),
        Country(name="France", code="fr"),
    ])

class Migration(migrations.Migration):

    dependencies = []

    operations = [
        migrations.RunPython(forwards_func, lambda apps, schema_editor: None),
    ]

यह Django 1.8, 1.9 के लिए काम करता है


अपडेट: इस लेखन की एक बेहतर तरीका बदलने के लिए किया जाएगा lambda apps, schema_editor: Noneके साथ migrations.RunPython.noopऊपर स्निपेट में। ये दोनों कार्यात्मक रूप से एक ही चीज हैं। (टिप्पणियों का श्रेय)


5
Django 1.8 के बाद से, आपको RunPython.noopइनलाइन लैम्ब्डा या समतुल्य के
स्पूनमाइज़र

@SpoonMeiser उदाहरण के वाक्य रचना में, मुझे लगता है कि जैसा दिखता है migrations.RunPython(forwards_func, migrations.RunPython.noop)। इसे कार्यात्मक रूप से जांचने की आवश्यकता है। इसे उत्तर के रूप में जोड़ा जाना चाहिए या इसे किसी समय संपादित करना चाहिए।
एलनसी

13

यहाँ मेरा समाधान है, क्योंकि उपरोक्त समाधान वास्तव में उपयोग-केस को कवर नहीं करता है, जब आप उपयोग करते हैं RunPython

आप ORM के माध्यम से तालिका तक पहुँच सकते हैं

from django.db.migrations.recorder import MigrationRecorder

>>> MigrationRecorder.Migration.objects.all()
>>> MigrationRecorder.Migration.objects.latest('id')
Out[5]: <Migration: Migration 0050_auto_20170603_1814 for model>
>>> MigrationRecorder.Migration.objects.latest('id').delete()
Out[4]: (1, {u'migrations.Migration': 1})

तो आप तालिकाओं को क्वेरी कर सकते हैं और उन प्रविष्टियों को हटा सकते हैं जो आपके लिए प्रासंगिक हैं। इस तरह से आप विस्तार से बता सकते हैं। RynPythonमाइग्रेशन के साथ आपको उन डेटा का भी ध्यान रखना होगा जो जोड़े / बदले / निकाले गए थे। उपरोक्त उदाहरण केवल प्रदर्शित करता है, कि आप Djang ORM के माध्यम से तालिका का उपयोग कैसे करते हैं।


फॉरेनकेय के साथ नए मॉडल बनाते समय, कई माइग्रेशन के साथ, फिर सभी को महसूस करना गलत है, और नए मॉडल के साथ कभी-कभी 2-3 माइग्रेशन को फिर से शुरू करना, लेकिन कभी-कभी एक ही मॉडल के नाम या एक ही रिश्ते के नाम ... यह समाधान स्पष्ट रूप से विजेता है। मेरे पास त्रुटि संदेश था जैसे django.db.utils.ProgrammingError: relation "<relation name>" already existsमैंने बनाया migrate --fakeजो कि गलत है, इसलिए मैंने वापस जाने की कोशिश की, फिर मुझे psycopg2.ProgrammingError: relation "<other <relation name>" does not existधन्यवाद मिला
onekiloparsec

10

दूसरी चीज़ जो आप कर सकते हैं, वह मैन्युअल रूप से बनाई गई तालिका को हटाना है।

इसके साथ ही, आपको उस विशेष माइग्रेशन फ़ाइल को हटाना होगा। साथ ही, आपको उस विशेष प्रविष्टि को django-migrations तालिका (संभवतः आपके मामले में अंतिम एक) को हटाना होगा जो उस विशेष प्रवास से संबंधित है।


इस मामले में सावधानी बरतें - आप पर्याप्त होने के लिए db को सत्यापित करने के लिए बाध्य हैं।
स्लावोमिर लेनार्ट

4
मैं बहुत सावधान जोड़ना होगा। आप Postgres में बहुत सी चीजों को तोड़ सकते हैं, उदाहरण के लिए बाधाओं।
जॉयबॉर्ग

9

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

python manage.py showmigrations
python manage.py migrate {app name from show migrations} {00##_migration file.py}

माइग्रेशन फ़ाइल हटाएं। एक बार वांछित माइग्रेशन आपके मॉडल में है ...

python manage.py makemigrations
python manage.py migrate

8

मैंने यह 1.9.1 में किया था (बनाए गए अंतिम या नवीनतम माइग्रेशन को हटाने के लिए):

  1. rm <appname>/migrations/<migration #>*

    उदाहरण: rm myapp/migrations/0011*

  2. डेटाबेस में लॉग इन किया और इस एसक्यूएल (इस उदाहरण में पोस्टग्रेज) को चलाया

    delete from django_migrations where name like '0011%';

मैं तब नया माइग्रेशन बनाने में सक्षम था जो माइग्रेशन नंबर के साथ शुरू हुआ था जिसे मैंने अभी हटा दिया था (इस मामले में, 11)।


1
+1 हालांकि यह काम करेगा, आपको अंतिम उपाय के रूप में इस तरह से बचाने की जरूरत है। इसके अलावा आपको स्तंभ / तालिकाओं को संपादित / ड्रॉप करना याद रखना होगा जिनमें समस्याग्रस्त प्रवासन का योगदान था।
nehem

अच्छा बिंदु - मैंने इसका उपयोग तब किया था जब मैंने एक माइग्रेशन बनाया था, लेकिन चला नहीं था "./manage.py माइग्रेट" अभी तक
MIkee

3

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

... नया माइग्रेशन बनाए बिना माइग्रेशन हटाएं?

टीएल; डीआर : आप मॉडल को ठीक करने के बाद कुछ अंतिम उलटे (भ्रमित) माइग्रेशन को हटा सकते हैं और एक नया बना सकते हैं । माइग्रेट कमांड द्वारा तालिका न बनाने के लिए इसे कॉन्फ़िगर करने के लिए आप अन्य विधियों का भी उपयोग कर सकते हैं । अंतिम माइग्रेशन बनाया जाना चाहिए ताकि यह वर्तमान मॉडल से मेल खाए


मामले में किसी को एक मॉडल के लिए एक तालिका क्यों नहीं बनानी चाहिए जो मौजूद होनी चाहिए:

ए) ऐसी कोई तालिका किसी भी मशीन और बिना शर्तों के डेटाबेस में मौजूद नहीं होनी चाहिए

  • कब: यह एक आधार मॉडल है जो केवल अन्य मॉडल के मॉडल वंशानुक्रम के लिए बनाया गया है।
  • समाधान: सेट करेंclass Meta: abstract = True

बी) टेबल को शायद ही कभी किसी और चीज से या विशेष तरीके से मैन्युअल रूप से बनाया जाता है।

  • समाधान: उपयोग class Meta: managed = False
    माइग्रेशन बनाया जाता है, लेकिन इसका उपयोग कभी नहीं किया जाता है, केवल परीक्षणों में। माइग्रेशन फ़ाइल महत्वपूर्ण है, अन्यथा डेटाबेस परीक्षण नहीं चल सकते हैं, प्रारंभिक स्थिति से शुरू हो सकते हैं।

ग) तालिका केवल कुछ मशीन (जैसे विकास में) पर उपयोग की जाती है।

  • समाधान: मॉडल को एक नए एप्लिकेशन में ले जाएं जो केवल विशेष परिस्थितियों में INSTALLED_APPS में जोड़ा गया है या एक सशर्त का उपयोग करता है class Meta: managed = some_switch

डी) परियोजना में कई डेटाबेस का उपयोग करता हैsettings.DATABASES

  • समाधान: डेटाबेस को अलग करने के लिए डेटाबेस राउटर को विधि के साथ लिखें allow_migrateजहां तालिका बनाई जानी चाहिए और जहां नहीं।

माइग्रेशन Django 1.9+ के साथ सभी मामलों ए), बी), सी), डी) में बनाया गया है (और केवल मामलों में बी, सी, डी Django 1.8 के साथ), लेकिन केवल उपयुक्त मामलों में डेटाबेस पर लागू होता है या शायद कभी नहीं इसकी आवश्यकता है। Django 1.8 के बाद से परीक्षण चलाने के लिए माइग्रेशन आवश्यक है। पूर्ण प्रासंगिक वर्तमान स्थिति को भी प्रबंधन के साथ मॉडल के लिए दर्ज किया गया है। Django 1.9+ में प्रबंधित किए गए = गलत तरीके से प्रबंधित / अप्रबंधित मॉडल के बीच फॉरेनके बनाने के लिए संभव हो सकता है या मॉडल को प्रबंधित कर सकते हैं = सही बाद में। (यह सवाल Django 1.8 के समय में लिखा गया है। यहां सब कुछ 1.8 से वर्तमान 2.2 के बीच के संस्करणों के लिए मान्य होना चाहिए।)

यदि अंतिम माइग्रेशन है (हैं) आसानी से नहीं बदला जा सकता है तो सावधानीपूर्वक (डेटाबेस बैकअप के बाद) एक नकली रिवर्ट करना संभव है ./manage.py migrate --fake my_app 0010_previous_migration, तालिका को मैन्युअल रूप से हटा दें।

यदि आवश्यक हो, तो निर्धारित मॉडल से एक निश्चित माइग्रेशन बनाएं और डेटाबेस संरचना को बदलने के बिना इसे लागू करें ./manage.py migrate --fake my_app 0011_fixed_migration


3

यदि आप माइग्रेशन को वापस करते समय परेशानी का सामना कर रहे हैं, और किसी तरह इसे गड़बड़ कर दिया है, तो आप fakeमाइग्रेशन कर सकते हैं ।

./manage.py migrate <name> --ignore-ghost-migrations --merge --fake

के लिए Django संस्करण <1.7 इस में प्रविष्टि बनाएगा south_migrationhistoryमेज, तो आप उस प्रविष्टि को हटाने की जरूरत है।

अब आप माइग्रेशन को आसानी से वापस कर पाएंगे।

पुनश्च: मैं बहुत समय से अटका हुआ था और नकली प्रवास कर रहा था और फिर वापस लौटने से मुझे मदद मिली।


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