Search code examples
django-fixturesdjango-sitesdjango-migrations

Django Sites Framework: Initial Data Migration Location


Before Django 1.7, when using the Django Sites Framework one could/should define the initial data using Initial Fixtures.

myproject/fixtures/initial_data.json

[
  {
    "pk": 1,
    "model": "sites.site",
    "fields": {
      "domain": "domain1",
      "name": "name1"
    }
  },
  {
    "pk": 2,
    "model": "sites.site",
    "fields": {
      "domain": "domain2",
      "name": "name2"
    }
  },
  {
    "pk": 3,
    "model": "sites.site",
    "fields": {
      "domain": "domain3",
      "name": "name3"
    }
  }
]

Since it is a global project setting, I added a "fixtures" folder to the project root, and added it to FIXTURE_DIRS.

# Used to search fixture files directories.
# Fixture files are files that provide initial data to be
# inserted in the database. (>python manage.py loaddata)

    FIXTURE_DIRS = [
        os.path.join(PROJECT_ROOT, "fixtures"),
    ]

Now, I'm using Django 1.7, and it is recommended to use migrations. Quoting Django documentation:

To set the correct name and domain for your project, you can use a data migration.

The problem is Migrations are app-specific:

python manage.py makemigrations --empty yourappname

So, what is the recommended approach to add the Site information to my project, using a data migration? Where should this migration live?

Running python manage.py makemigrations --empty sites creates the migration in the third party app folder, so we don't want that.

Shouldn't be possible to define a MIGRATION_DIRS as FIXTURE_DIRS existed for the initial_data?

I found MIGRATION_MODULES in settings documentation, but the problem still remains, it is app-specific.


Solution

  • First, configure MODULE_MIGRATIONS in your django settings:

    MIGRATION_MODULES = {
        'sites': 'myproject.fixtures.sites_migrations',
    }
    

    Then, run ./manage.py makemigrations sites to have django create the directory and create 0001_intitial.py in the myproject.fixtures.sites_migrations package.

    Then, do ./manage.py makemigrations --empty sites. The migration file should be created in the specified package.

    My file 0002_initialize_sites.py looks like this:

    from __future__ import unicode_literals
    
    from django.db import migrations
    
    
    def insert_sites(apps, schema_editor):
        """Populate the sites model"""
        Site = apps.get_model('sites', 'Site')
        Site.objects.all().delete()
    
        # Register SITE_ID = 1
        Site.objects.create(domain='create.tourtodo.com', name='create')
        # Register SITE_ID = 2
        Site.objects.create(domain='www.tourtodo.com', name='www')
    
    
    class Migration(migrations.Migration):
    
        dependencies = [
            ('sites', '0001_initial'),
        ]
    
        operations = [
            migrations.RunPython(insert_sites)
        ]