1. ホーム
  2. python

[解決済み] Django 1.7とデータマイグレーションで初期データを読み込む

2023-01-17 03:40:45

質問

私は最近 Django 1.6 から 1.7 に乗り換え、migrations を使い始めました (South は使ったことがありませんでした)。

1.7 以前、私は初期データをロードするために fixture/initial_data.json というファイルを読み込んでいましたが、これは python manage.py syncdb コマンド(データベース作成時)で読み込まれたものです。

現在、私はmigrationsを使い始めましたが、この動作は非推奨です :

アプリケーションが migrations を使っている場合、フィクスチャの自動読み込みは行われません。 Django 2.0 では migrations がアプリケーションに必要になるため、この動作は非推奨とされています。アプリの初期データをロードしたい場合は、データマイグレーションで行うことを検討し てください。 ( https://docs.djangoproject.com/en/1.7/howto/initial-data/#automatically-loading-initial-data-fixtures )

この 公式ドキュメント には、その方法についての明確な例がないので、私の質問は:

データ移行を使用してこのような初期データをインポートする最良の方法は何でしょうか。

  1. を複数回呼び出すPythonコードを書いてください。 mymodel.create(...) ,
  2. Django の関数を使うか書くか ( を呼び出すように loaddata を呼び出して、JSONフィクスチャファイルからデータをロードします。

私は2番目のオプションを好みます。

今はDjangoがネイティブでできるようなので、Southは使いたくないです。

どのように解決するのですか?

更新 : このソリューションが引き起こす可能性のある問題については、以下の @GwynBleidD のコメントを参照してください。また、将来のモデル変更に対してより耐久性のあるアプローチについては、以下の @Rockallite の回答を参照してください。


フィクスチャファイルが <yourapp>/fixtures/initial_data.json

  1. 空のマイグレーションを作成します。

    Django 1.7 では。

    python manage.py makemigrations --empty <yourapp>
    
    

    Django 1.8+ では、名前を指定することができます。

    python manage.py makemigrations --empty <yourapp> --name load_intial_data
    
    
  2. マイグレーションファイルの編集 <yourapp>/migrations/0002_auto_xxx.py

    2.1. Djangoに触発されたカスタム実装 loaddata (最初の回答)。

    import os
    from sys import path
    from django.core import serializers
    
    fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures'))
    fixture_filename = 'initial_data.json'
    
    def load_fixture(apps, schema_editor):
        fixture_file = os.path.join(fixture_dir, fixture_filename)
    
        fixture = open(fixture_file, 'rb')
        objects = serializers.deserialize('json', fixture, ignorenonexistent=True)
        for obj in objects:
            obj.save()
        fixture.close()
    
    def unload_fixture(apps, schema_editor):
        "Brutally deleting all entries for this model..."
    
        MyModel = apps.get_model("yourapp", "ModelName")
        MyModel.objects.all().delete()
    
    class Migration(migrations.Migration):  
    
        dependencies = [
            ('yourapp', '0001_initial'),
        ]
    
        operations = [
            migrations.RunPython(load_fixture, reverse_code=unload_fixture),
        ]
    
    

    2.2. のよりシンプルな解決策 load_fixture をよりシンプルにしました (@juliocesar さんの提案による)。

    from django.core.management import call_command
    
    fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures'))
    fixture_filename = 'initial_data.json'
    
    def load_fixture(apps, schema_editor):
        fixture_file = os.path.join(fixture_dir, fixture_filename)
        call_command('loaddata', fixture_file) 
    
    

    カスタムディレクトリを使用したい場合に便利です。

    2.3. 最もシンプル。 呼び出し loaddataapp_label は、フィクスチャを <yourapp> 's fixtures のディレクションを自動的に行います。

    from django.core.management import call_command
    
    fixture = 'initial_data'
    
    def load_fixture(apps, schema_editor):
        call_command('loaddata', fixture, app_label='yourapp') 
    
    

    を指定しない場合 app_label を指定しないと、loaddata は fixture からファイル名を読み込もうとします。 全て アプリのフィクスチャディレクトリ(これはおそらく必要ないでしょう)。

  3. 実行する

    python manage.py migrate <yourapp>