Django loaddata在迁移中调用时会引发IntegrityError,但从CLI调用时会起作用

Django loaddata在迁移中调用时会引发IntegrityError,但从CLI调用时会起作用,django,django-migrations,django-fixtures,django-manage.py,loaddata,Django,Django Migrations,Django Fixtures,Django Manage.py,Loaddata,对于我的Django 1.8.12站点,我有一个example\u contentfixture来填充一些初始站点内容 如果我在运行migrate后立即加载此文件,它将很好地导入: $ ./manage.py migrate --noinput Operations to perform: Synchronize unmigrated apps: ckeditor, staticfiles, zinnia_ckeditor, messages, djangocms_admin_style,

对于我的Django 1.8.12站点,我有一个
example\u content
fixture来填充一些初始站点内容

如果我在运行
migrate
后立即加载此文件,它将很好地导入:

$ ./manage.py migrate --noinput
Operations to perform:
  Synchronize unmigrated apps: ckeditor, staticfiles, zinnia_ckeditor, messages, djangocms_admin_style, webapp_creator, template_debug, sekizai, django_pygments, treebeard
  Apply all migrations: djangocms_inherit, djangocms_snippet, api_docs, cmsplugin_zinnia, sites, menus, contenttypes, store_data, zinnia, django_comments, sessions, rev
ersion, auth, djangocms_picture, tagging, developer_portal, admin, djangocms_link, djangocms_video, django_openid_auth, md_importer, cms, djangocms_text_ckeditor
Synchronizing apps without migrations:
  Creating tables...
    Running deferred SQL...
  Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  ... (skipped for brevity).
  Applying django_comments.0003_add_submit_date_index... OK
$ ./manage.py loaddata example_content
Installed 139582 object(s) from 1 fixture(s)
$
但是,我希望此数据在
migrate
时自动导入,而不需要额外的手动
loaddata
步骤,因此我正在尝试创建一个迁移,
my_app.0002_example_content
,以调用
loaddata
命令

我通过在每个相关模块上添加依赖项来确保首先加载所有其他数据

为了确认此迁移确实是最后一次运行(正如上面成功运行时一样),我首先注释掉了
RunPython
步骤,将迁移留空:

# my_app/migrations/0002_example_content.py

from django.core.management import call_command
from django.db import models, migrations

class Migration(migrations.Migration):
    from django.core.management import call_command
    from django.db import models, migrations

    dependencies = [
        ('djangocms_inherit', '0002_auto_20150622_1244'),
        ... all other apps (skipped for brevity)
        ('my_app', '0001_initial'),
    ]
    operations = [
#        migrations.RunPython(
#            lambda apps, schema_editor: call_command("loaddata", "example_content")
#        )
    ]
确实,它会作为最后一次迁移运行:

$ ./manage.py migrate --noinput
Operations to perform:
  Synchronize unmigrated apps: ckeditor, staticfiles, zinnia_ckeditor, messages, djangocms_admin_style, webapp_creator, template_debug, sekizai, django_pygments, treebeard
  Apply all migrations: djangocms_inherit, djangocms_snippet, api_docs, cmsplugin_zinnia, sites, menus, contenttypes, store_data, zinnia, django_comments, sessions, reversion, auth, djangocms_picture, tagging, developer_portal, admin, djangocms_link, djangocms_video, django_openid_auth, md_importer, cms, djangocms_text_ckeditor
Synchronizing apps without migrations:
  Creating tables...
    Running deferred SQL...
  Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  ... (skipped for brevity)
  Applying django_comments.0003_add_submit_date_index... OK
  Applying my_app.0001_initial... OK
  Applying my_app.0002_example_content... OK
$
但是,当我尝试运行它以实际运行
loaddata
命令(在中注释代码)时,我得到一个错误:

$ ./manage.py migrate --noinput
Operations to perform:
  Synchronize unmigrated apps: ckeditor, staticfiles, zinnia_ckeditor, messages, djangocms_admin_style, webapp_creator, template_debug, sekizai, django_pygments, treebeard
  Apply all migrations: djangocms_inherit, djangocms_snippet, api_docs, cmsplugin_zinnia, sites, menus, contenttypes, store_data, zinnia, django_comments, sessions, reversion, auth, djangocms_picture, tagging, developer_portal, admin, djangocms_link, djangocms_video, django_openid_auth, md_importer, cms, djangocms_text_ckeditor
Synchronizing apps without migrations:
  Creating tables...
    Running deferred SQL...
  Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  ... (skipped for brevity)
  Applying django_comments.0003_add_submit_date_index... OK
  Applying my_app.0001_initial... OK
  Applying my_app.0002_example_content...Traceback (most recent call last):
...
django.db.utils.IntegrityError: Problem installing fixtures: The row in table 'django_comments' with primary key '1' has an invalid foreign key: django_comments.content
_type_id contains a value '37' that does not have a corresponding value in django_content_type.id.
考虑到我的新迁移肯定是在其他一切之后运行的,所以顺序应该与我手动调用
loaddata
时完全相同。因此,我不明白为什么通过CLI调用它会成功,但通过迁移调用它会失败


是否在
migrate
步骤结束时发生了一些我遗漏的事情,这可能解释了这里的差异?

Django使用
post\u migrate
信号创建缺少的内容类型,因此如果这是您第一次在当前数据库上迁移,在运行加载数据的迁移之前,内容类型将不存在

您可以手动创建迁移中所需的内容类型。Django将检测现有的内容类型,并且不会创建任何副本


请注意,内容类型的特定id可能因数据库而异。使用转储数据可能更好

Django使用一个
post_migrate
信号来创建缺少的内容类型,因此,如果这是您第一次在当前数据库上进行迁移,则在运行加载数据的迁移之后,内容类型才会存在

您可以手动创建迁移中所需的内容类型。Django将检测现有的内容类型,并且不会创建任何副本

请注意,内容类型的特定id可能因数据库而异。使用转储数据可能更好

在的提示下,我设法解决了这个问题

起初我试着手动打电话,但自己打不起作用。事实证明,我需要实际调用所有信号,因为我想他们需要做更多的整理工作

以下是我的应用程序0002示例内容

# my_app/migrations/0002_example_content.py

from django.core.management import call_command
from django.db import migrations
from django.apps import apps
from django.db.models.signals import post_migrate


def finish_previous_migrations(migrate_apps):
    """
    Explicitly run the post_migrate actions
    for all apps
    """

    for app_config in apps.get_app_configs():
        post_migrate.send(
            sender=app_config,
            app_config=app_config
        )


def load_site_content(migrate_apps, schema_editor):
    """
    Load the website content fixture
    """

    finish_previous_migrations(migrate_apps)

    call_command("loaddata", "example_content")


class Migration(migrations.Migration):
    dependencies = [
        ('djangocms_inherit', '0002_auto_20150622_1244'),
        ... all other apps (skipped for brevity)
        ('my_app', '0001_initial'),
    ]
    operations = [
        migrations.RunPython(load_site_content)
    ]
在他的鼓励下,我设法解决了这个问题

起初我试着手动打电话,但自己打不起作用。事实证明,我需要实际调用所有信号,因为我想他们需要做更多的整理工作

以下是我的应用程序0002示例内容

# my_app/migrations/0002_example_content.py

from django.core.management import call_command
from django.db import migrations
from django.apps import apps
from django.db.models.signals import post_migrate


def finish_previous_migrations(migrate_apps):
    """
    Explicitly run the post_migrate actions
    for all apps
    """

    for app_config in apps.get_app_configs():
        post_migrate.send(
            sender=app_config,
            app_config=app_config
        )


def load_site_content(migrate_apps, schema_editor):
    """
    Load the website content fixture
    """

    finish_previous_migrations(migrate_apps)

    call_command("loaddata", "example_content")


class Migration(migrations.Migration):
    dependencies = [
        ('djangocms_inherit', '0002_auto_20150622_1244'),
        ... all other apps (skipped for brevity)
        ('my_app', '0001_initial'),
    ]
    operations = [
        migrations.RunPython(load_site_content)
    ]

啊,就是这样!你知道有没有办法手动创建所有内容类型,就像
post\u migrate
那样?Django使用创建它们。啊,就是这样!您知道是否有任何方法可以手动创建所有内容类型,方法与
post\u migrate
相同吗?Django使用。