Django Sites Framework: Initial Data Migration Location

南笙酒味 提交于 2019-11-27 17:41:45

问题


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.


回答1:


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:

-*- coding: utf-8 -*-
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)
    ]



回答2:


You just need to reference the highest-numbered sites migration as a dependency.

def forward(apps, schema_editor):
    Site = apps.get_model("sites", "Site")
    db_alias = schema_editor.connection.alias
    s, created = Site.objects.using(db_alias).get_or_create(pk=1)
    s.name = APP_NAME
    s.domain = APP_NAME
    s.save()


def reverse(apps, schema_editor):
    Site = apps.get_model("sites", "Site")
    db_alias = schema_editor.connection.alias
    s = Site.objects.using(db_alias).get(pk=1)
    s.name = ORIG_APP_NAME
    s.domain = ORIG_APP_NAME
    s.save()


class Migration(migrations.Migration):

    dependencies = [

        # `core` is the app containing this migration
        ('core', '0001_initial'),

        # `0002_alter_domain_unique` is the highest-numbered migration for
        # the sites framework
        ('sites', '0002_alter_domain_unique'),

    ]

    operations = [
        migrations.RunPython(forward, reverse)
    ]

This was tested on Django 1.11.2.

Fwiw, the MODULE_MIGRATIONS solution above does not work for me.




回答3:


A couple of tweaks to @Jason's answer. Last tested with Django 2.2.

from django.conf import settings
from django.db import migrations


def update_site_domain(apps, schema_editor):
    Site = apps.get_model("sites", "Site")
    s, _ = Site.objects.get_or_create(pk=settings.SITE_ID)
    s.domain = settings.HOST
    s.save()


class Migration(migrations.Migration):

    dependencies = [
        ("your_app", "last_migration_name"),
        ("sites", "0002_alter_domain_unique"),  # highest-numbered migration for the sites framework
    ]

    operations = [migrations.RunPython(update_site_domain)]


来源:https://stackoverflow.com/questions/26127830/django-sites-framework-initial-data-migration-location

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!