Loading initial data with Django 1.7 and data migrations

前端 未结 7 1942
陌清茗
陌清茗 2020-11-27 09:39

I recently switched from Django 1.6 to 1.7, and I began using migrations (I never used South).

Before 1.7, I used to load initial data with a fixture/initial_d

7条回答
  •  时光取名叫无心
    2020-11-27 10:32

    Update: See @GwynBleidD's comment below for the problems this solution can cause, and see @Rockallite's answer below for an approach that's more durable to future model changes.


    Assuming you have a fixture file in /fixtures/initial_data.json

    1. Create your empty migration:

      In Django 1.7:

      python manage.py makemigrations --empty 
      

      In Django 1.8+, you can provide a name:

      python manage.py makemigrations --empty  --name load_intial_data
      
    2. Edit your migration file /migrations/0002_auto_xxx.py

      2.1. Custom implementation, inspired by Django' loaddata (initial answer):

      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. A simpler solution for load_fixture (per @juliocesar's suggestion):

      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) 
      

      Useful if you want to use a custom directory.

      2.3. Simplest: calling loaddata with app_label will load fixtures from the 's fixtures dir automatically :

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

      If you don't specify app_label, loaddata will try to load fixture filename from all apps fixtures directories (which you probably don't want).

    3. Run it

      python manage.py migrate 
      

提交回复
热议问题