web-dev-qa-db-ja.com

Django andSouthでアプリの名前を変更する

アプリケーションの名前をより適切な名前に変更しています。そうすることで、 South がデータベースを適切に移行することを確認したいと思います(データベーステーブルの名前を変更し、Django_content_typeまたはsouth_migrationhistoryの参照を変更します)。 モデルを別のアプリに移行する 方法は知っていますが、アプリ自体の名前を変更しようとすると、Southは移行履歴を正しく認識しません。

望ましくない解決策old_appの名前をnew_appに変更する際に、old_app/migrationsをそのままにして、このディレクトリに新しい移行を追加することができますデータベースを参照new_appに移行します。

可能であれば、ディレクトリold_appを完全に削除したいと思います。私はまだこの問題のより良い解決策を考えていません。

データを失うことなくDjango Southでアプリの名前を変更する最良の方法は何ですか?

32
Trey Hunner

私はあなたがこの状況を避けるべきであるというラクシャムに同意します。しかし、時々、私たちはしなければなりません。私は過去にこの状況に直面し、このように管理してきました。

データの損失を回避したい場合は、古いアプリケーションデータをjsonファイルにダンプできます。

python manage.py dumpdata old_app --natural --indent=4 1> old_app.json

コンテンツタイプを自然キー(app_name、model)で強制的にエクスポートする--naturalオプションに注意してください。

次に、このjsonファイルを開き、すべてのold_app参照をnew_appに置き換える小さなコマンドを作成できます。

このようなものが機能するはずです

class Command(BaseCommand):
    help = u"Rename app in json dump"

    def handle(self, *args, **options):
        try:
            old_app = args[0]
            new_app = args[1]
            filename = args[2]
        except IndexError:
            print u'usage :', __name__.split('.')[-1], 'old_app new_app dumpfile.json'
            return

        try:
            dump_file = open(filename, 'r')
        except IOError:
            print filename, u"doesn't exist"
            return

        objects = json.loads(dump_file.read())
        dump_file.close()

        for obj in objects:
            obj["model"] = obj["model"].replace(old_app, new_app, 1)

            if obj["fields"].has_key("content_type") and (old_app == obj["fields"]["content_type"][0]):
                obj["fields"]["content_type"][0] = new_app

        dump_file = open(filename, 'w')
        dump_file.write(json.dumps(objects, indent=4))
        dump_file.close()

次に、アプリケーションの名前を変更し、INSTALLED_APPSで名前を変更します。

次に、すべての南の移行を削除し、新しいアプリの初期移行を再生成して適用する必要があります。次に、SQLコマンドを実行します。

update Django_content_type set app_label='new_app' where app_label='old_app'

次に、テーブルを作成してjsonファイルを読み込むために、新しいアプリのサウスマイグレーションを起動します。

python manage.py loaddata old_app.json

私はプロジェクトで同様のことをしましたが、うまくいくようです。

お役に立てば幸いです

44
luc

アプリの名前を変更することが可能です。サンプルプロジェクトとして、以下を参照してください。

https://github.com/ASKBOT/Django-south-app-rename-example

基本的に、2つの移行があります。最初にテーブルの名前がdb.rename_table()を使用して変更され、次にコンテンツタイプが更新されます。これは、if not db.dry_run:をチェックすることにより、1つの移行に組み合わせることができます。その例については、 モデルを1つのDjangoアプリから新しいモデルに移行するにはどうすればよいですか? )を参照してください。

最初の移行では、既存のテーブルがある場合は、それらの名前を直接変更できます。

if 'old_app_table_name' in connection.introspection.table_names():
    db.rename_table('old_app_table_name', 'new_app_table_name')
else:
    # Create new app tables directly.

より多くの移行があるテーブルの場合、古い移行名がすでに適用されているかどうかを確認する必要がある場合があります。

from south.models import MigrationHistory
if MigrationHistory.objects.exists(app_name='old_app', migration='0001_initial'):
    return

最後に、IDE(PyCharmトライアルなど)を使用してパッケージの名前を変更することをお勧めします(右クリック、リファクタリング->パッケージの名前変更)。これにより、アプリケーション全体のすべての使用法が更新されます。 URLconf、設定、インポートを含みます。

24
vdboor

少し差し込んだ後、私はこれを思いついた。それの世話をする必要があります。 https://Gist.github.com/jamesmfriedman/61680

8
jamesmfriedman

免責事項:この回答は、移行履歴を気にせず、アプリの名前を変更してすでに混乱していて、移行を完全に忘れている人向けです(私が行ったように)。私のために働いた。

フォルダー名を変更し、コード内のすべてのインポートを処理し、settings.INSTALLED_APPSで対応するアプリ名を変更した後、以前のすべての移行フォルダーを削除するだけです。次に、このような最初のものを作成します

manage.py schemamigration new_app --initial

そして、それを適用するとき、このようにそれを偽造します

manage.py migrate new_app 0001 --fake

-偽造することを忘れないでください。そうしないと、データが失われる可能性があります

それ以降のすべての移行は問題なく機能します

manage.py migrate new_app 0002

また、app_name = "old_app"であるsouth_migrationhistoryから削除することもできます。

1