django.db.migrations.exceptions.InconsistentMigrationHistory

时间:2017-06-20 11:25:22

标签: python django django-models django-rest-framework database-migration

当我跑步时

python manage.py migrate

在我的django项目中,我收到以下错误

Traceback (most recent call last):
File "manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "/home/hari/project/env/local/lib/python2.7/site-     packages/django/core/management/__init__.py", line 363, in execute_from_command_line
utility.execute()
File "/home/hari/project/env/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 355, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/hari/project/env/local/lib/python2.7/site-packages/django/core/management/base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/hari/project/env/local/lib/python2.7/site-packages/django/core/management/base.py", line 330, in execute
output = self.handle(*args, **options)
File "/home/hari/project/env/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 86, in handle
executor.loader.check_consistent_history(connection)
File "/home/hari/project/env/local/lib/python2.7/site-packages/django/db/migrations/loader.py", line 298, in check_consistent_history
connection.alias,
django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependency account.0001_initial on database 'default'.

我有一个类似下面的用户模型

class User(AbstractUser):
place = models.CharField(max_length=64, null=True, blank=True)
address = models.CharField(max_length=128, null=True, blank=True)

那我怎么解决这个问题呢?

28 个答案:

答案 0 :(得分:47)

由于您使用的是自定义用户模型,因此您可以先注释掉

INSTALLED_APPS = [
...
#‘django.contrib.admin’,
...
]
在您的Installed_Apps设置中

。然后运行

python manage.py migrate.

完成取消注释后

‘django.contrib.admin’.

答案 1 :(得分:23)

让我们从本页的大多数答案解决问题开始:

如果您正确使用Django的迁移系统,那么 /强>

现在,最适合您的解决方案取决于许多因素,包括您对Django的体验,对迁移系统的理解程度,以及数据库中数据的价值。

简而言之,有两种方法可以解决任何迁移错误。

  1. 选择选项。 警告:这只是一个选项,你是独自工作。如果其他人依赖现有迁移,则无法删除它们。

    • 删除所有迁移,并使用python3 -m manage makemigrations重建一个新的集合。这应该可以消除您在迁移中遇到的依赖关系或不一致问题。
    • 删除整个数据库。这将消除您在实际数据库架构与基于迁移历史记录的架构之间存在的不一致所带来的任何问题,并将消除您在迁移历史记录与先前迁移文件之间存在不一致时遇到的任何问题[这就是InconsistentMigrationHistory正在抱怨]。
    • 使用python3 -m manage migrate
    • 重新创建数据库架构
  2. 确定错误的原因并解决它,因为(根据经验说)原因几乎可以肯定是所做的事情。 (通常由于不了解如何正确使用迁移系统)。根据我所导致的错误,有三个类别。

    1. 迁移文件不一致。当多个人正在处理项目时,这是一个非常常见的问题。希望您的更改不会发生冲突,makemigrations --merge可以解决此问题,否则有人将不得不将迁移回滚到分支点以解决此问题。
    2. 架构与迁移历史记录之间存在不一致。要管理此人,将手动编辑数据库架构或删除迁移。如果他们删除了迁移,那么还原他们的更改并对他们大喊大叫;如果其他人依赖它们,您应该从不删除迁移。如果他们手动编辑数据库模式,则还原他们的更改然后对它们大喊大叫; Django正在管理数据库模式,没有其他人。
    3. 迁移历史记录与迁移文件之间存在不一致。 [这是提问者遇到的InconsistentMigrationHistory问题,以及我到达此页面时遇到的问题]。为了管理这个,有人手动搞砸了django_migrations表,或者在应用后删除了迁移。要解决此问题,您将不得不弄清楚不一致的方式并手动解决它。如果您的数据库架构是正确的,并且只是您的迁移历史记录错误,您可以手动编辑django_migrations表来解决此问题。如果您的数据库架构错误,那么您还必须手动编辑它以使其与应有的一致。
  3. 根据您对问题的描述和您选择的答案,我将假设您是独自工作,不熟悉Django,并且不关心您的数据。所以核选项可能适合你。

    如果您不处于这种情况并且上述文字看起来像胡言乱语,那么我建议您向Django User's Mailing List寻求帮助。那里有非常有帮助的人可以帮助您解决您所处的特定问题。

    有信心,你可以解决这个错误而不去核!

答案 2 :(得分:18)

数据库中的django_migrations表是导致不一致的原因,只是从本地路径中删除所有迁移工作。

您必须从数据库中截断django_migrations表,然后再次尝试应用迁移。它应该工作,但如果没有,那么再次运行makemigrations然后迁移。

注意:请勿忘记备份数据。

答案 3 :(得分:10)

按照django文档中的建议,在添加自定义用户模型后,在新项目中发生了这种情况。

If you’re starting a new project, it’s highly recommended to set up a custom user model, even if the default User model is sufficient for you.

这是我解决问题的方法。

  1. 删除数据库db.sqlite3。
  2. 删除app / migrations文件夹。

每个@jackson,暂时将django.contrib.admin注释掉。

INSTALLED_APPS = [
...
#‘django.contrib.admin’,
...
]

还注释掉urls.py中的管理站点:

urlpatterns = [
    path('profile/', include('restapp.urls')),
    #path('admin/', admin.site.urls),
]

如果不注释路径(“ admin /”),则在运行时会出现错误“ LookupError:未安装带有标签“ admin”的应用”

python manage.py migrate

迁移完成后,请取消注释以上两项。

答案 4 :(得分:9)

这里如何妥善解决这个问题。

在项目内的迁移文件夹中执行以下步骤:

  1. 删除_pycache_和0001_initial文件。
  2. 从根目录中删除db.sqlite3(请注意,所有数据都将消失)。
  3. 在终端上运行:
      python manage.py makemigrations
                               python manage.py migrate
  4. 瞧。

答案 5 :(得分:2)

在执行任何其他步骤之前,请备份数据库。然后再次备份。

删除所有自定义用户模型代码,在设置中禁用自定义模型和应用,然后:

python manage.py dumpdata auth --natural-primary --natural-foreign > auth.json
python manage.py migrate auth zero  # This will also revert out the admin migrations

然后添加您的自定义模型,在设置中进行设置,然后重新启用该应用。确保您尚未在此应用上进行任何迁移。

然后:

python manage.py makemigrations <your-app>
python manage.py migrate
python manage.py loaddata auth.json  # Assumes your user-model isn't TOO dissimilar to the standard one.

完成!

答案 6 :(得分:2)

已解决此问题,然后在settings.py中进行迁移之前对此进行了评论 'django.contrib.admin' 并在urls.py中, ('admin/', admin.site.urls)。 迁移后取消注释

答案 7 :(得分:2)

问题

  

django.db.migrations.exceptions.InconsistentMigrationHistory:迁移admin.0001_initial在其依赖项帐户之前应用。0001_initial在数据库“默认”上。

因此我们可以首先在不使用admin(admin.0001_initial)的情况下迁移数据库。

迁移依赖项后,执行命令以迁移admin.0001_initial

解决方案

  1. 从INSTALLED_APPS中的settings.py中删除“ django.contrib.admin”。
  2. 执行命令:
  

Python manage.py makemigrations应用程序名称

     

Python manage.py迁移应用名称

  1. 在settings.py文件中的INSTALLED_APPS中添加“ django.contrib.admin”。
  2. 再次执行命令:
  

$:Python manage.py makemigrations应用程序名称

     

$:Python manage.py迁移应用名称

答案 8 :(得分:1)

如果您在 settings.py 中设置 AUTH_USER_MODE L,如下所示:

AUTH_USER_MODEL = 'custom_user_app_name.User'

您应该在运行 makemigration migration 命令之前对此行进行注释。然后,您可以再次取消注释此行。

答案 9 :(得分:1)

只需删除sqlite文件或运行刷新数据库'python manage.py flush' 然后分别运行makemigrations和migration命令。

答案 10 :(得分:1)

创建新的Django项目并运行

  

python manage.py迁移

默认情况下,Django会为您创建10个表,其中包括一个auth_user表和两个以auth_user开头的表。

当您要创建从AbstractUser继承的自定义用户模型时,您将遇到此问题,并显示以下错误消息:

django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependency account.0001_initial on database 'default'.

我通过删除整个数据库来解决此问题,并创建一个新数据库。这取代了我提到的三个表。

答案 11 :(得分:1)

我从Wagtail 2.0迁移到2.4时遇到了此问题,但是在第三方应用程序在当前版本之后(但要迁移到该版本之前)压榨迁移的其他几次

在这种情况下,令人震惊的简单解决方案至少是:

./manage.py migrate
./manage.py makemigrations
./manage.py migrate

即在尝试进行迁移之前先运行一次迁移。

答案 12 :(得分:1)

INSTALLED_APPS的顺序似乎很重要。 如果您始终将您的近期作品放在列表的顶部/开头,那么对于django.contrib.admin而言,它们将始终被正确加载。将我的作品移到INSTALLED_APPS列表的开头,为我解决了这个问题。 Kun Shi的解决方案可能奏效的原因也许是按照不同的顺序进行了迁移。

答案 13 :(得分:1)

如果您使用的是空数据库,则可以在进行其他任何应用迁移之前先快速解决帐户应用的迁移问题。

$ ./manage.py migrate account

然后:

$ ./manage.py migrate

答案 14 :(得分:1)

只需删除所有migrations文件夹、__pycache__.pyc文件:

find . | grep -E "(__pycache__|\.pyc|\.pyo$|migrations)" | xargs rm -rf

然后,运行:

python manage.py makemigrations
python manage.py migrate

答案 15 :(得分:0)

从已安装的应用程序中评论 django.contrib.admin 并评论路径('admin/', admin.site.urls),然后重新运行 makemigrations 然后迁移。它将解决您的问题。如需更多信息,请访问 here

答案 16 :(得分:0)

django.db.migrations.exceptions.InconsistentMigrationHistory#创建自定义用户模型

今天我遇到了同样的问题,以上解决方案均无效,然后我想使用以下命令从本地PostgreSQL数据库中删除所有数据

-- Drop everything from the PostgreSQL database.

DO $$
DECLARE
        q TEXT;
        r RECORD;
BEGIN
        -- triggers
        FOR r IN (SELECT pns.nspname, pc.relname, pt.tgname
                FROM pg_catalog.pg_trigger pt, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace AND pc.oid=pt.tgrelid
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pt.tgisinternal=false
            ) LOOP
                EXECUTE format('DROP TRIGGER %I ON %I.%I;',
                    r.tgname, r.nspname, r.relname);
        END LOOP;
        -- constraints #1: foreign key
        FOR r IN (SELECT pns.nspname, pc.relname, pcon.conname
                FROM pg_catalog.pg_constraint pcon, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace AND pc.oid=pcon.conrelid
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pcon.contype='f'
            ) LOOP
                EXECUTE format('ALTER TABLE ONLY %I.%I DROP CONSTRAINT %I;',
                    r.nspname, r.relname, r.conname);
        END LOOP;
        -- constraints #2: the rest
        FOR r IN (SELECT pns.nspname, pc.relname, pcon.conname
                FROM pg_catalog.pg_constraint pcon, pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace AND pc.oid=pcon.conrelid
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pcon.contype<>'f'
            ) LOOP
                EXECUTE format('ALTER TABLE ONLY %I.%I DROP CONSTRAINT %I;',
                    r.nspname, r.relname, r.conname);
        END LOOP;
        -- indicēs
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind='i'
            ) LOOP
                EXECUTE format('DROP INDEX %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- normal and materialised views
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind IN ('v', 'm')
            ) LOOP
                EXECUTE format('DROP VIEW %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- tables
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind='r'
            ) LOOP
                EXECUTE format('DROP TABLE %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- sequences
        FOR r IN (SELECT pns.nspname, pc.relname
                FROM pg_catalog.pg_class pc, pg_catalog.pg_namespace pns
                WHERE pns.oid=pc.relnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pc.relkind='S'
            ) LOOP
                EXECUTE format('DROP SEQUENCE %I.%I;',
                    r.nspname, r.relname);
        END LOOP;
        -- extensions (only if necessary; keep them normally)
        FOR r IN (SELECT pns.nspname, pe.extname
                FROM pg_catalog.pg_extension pe, pg_catalog.pg_namespace pns
                WHERE pns.oid=pe.extnamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
            ) LOOP
                EXECUTE format('DROP EXTENSION %I;', r.extname);
        END LOOP;
        -- aggregate functions first (because they depend on other functions)
        FOR r IN (SELECT pns.nspname, pp.proname, pp.oid
                FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pns, pg_catalog.pg_aggregate pagg
                WHERE pns.oid=pp.pronamespace
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
                    AND pagg.aggfnoid=pp.oid
            ) LOOP
                EXECUTE format('DROP AGGREGATE %I.%I(%s);',
                    r.nspname, r.proname,
                    pg_get_function_identity_arguments(r.oid));
        END LOOP;
        -- routines (functions, aggregate functions, procedures, window functions)
        IF EXISTS (SELECT * FROM pg_catalog.pg_attribute
                WHERE attrelid='pg_catalog.pg_proc'::regclass
                    AND attname='prokind' -- PostgreSQL 11+
            ) THEN
                q := 'CASE pp.prokind
                        WHEN ''p'' THEN ''PROCEDURE''
                        WHEN ''a'' THEN ''AGGREGATE''
                        ELSE ''FUNCTION''
                    END';
        ELSIF EXISTS (SELECT * FROM pg_catalog.pg_attribute
                WHERE attrelid='pg_catalog.pg_proc'::regclass
                    AND attname='proisagg' -- PostgreSQL ≤10
            ) THEN
                q := 'CASE pp.proisagg
                        WHEN true THEN ''AGGREGATE''
                        ELSE ''FUNCTION''
                    END';
        ELSE
                q := '''FUNCTION''';
        END IF;
        FOR r IN EXECUTE 'SELECT pns.nspname, pp.proname, pp.oid, ' || q || ' AS pt
                FROM pg_catalog.pg_proc pp, pg_catalog.pg_namespace pns
                WHERE pns.oid=pp.pronamespace
                    AND pns.nspname NOT IN (''information_schema'', ''pg_catalog'', ''pg_toast'')
            ' LOOP
                EXECUTE format('DROP %s %I.%I(%s);', r.pt,
                    r.nspname, r.proname,
                    pg_get_function_identity_arguments(r.oid));
        END LOOP;
        -- nōn-default schemata we own; assume to be run by a not-superuser
        FOR r IN (SELECT pns.nspname
                FROM pg_catalog.pg_namespace pns, pg_catalog.pg_roles pr
                WHERE pr.oid=pns.nspowner
                    AND pns.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast', 'public')
                    AND pr.rolname=current_user
            ) LOOP
                EXECUTE format('DROP SCHEMA %I;', r.nspname);
        END LOOP;
        -- voilà
        RAISE NOTICE 'Database cleared!';
END; $$;

此后,您可以运行django命令进行迁移

python manage.py makemigrations
python manage.py migrate

绝对可以。谢谢。

答案 17 :(得分:0)

删除迁移文件夹和db.sqlite3,然后输入cmd python manage.py makemigrations

答案 18 :(得分:0)

我必须将数据库拖放到其中,然后运行makemigrations并再次迁移,才能由我自己解决。

答案 19 :(得分:0)

当您对默认用户模型进行一些更改或通过 abstractuser 创建自定义用户模型时,很多时候您都会遇到该错误

1:请记住,当我们创建超级用户时,我们需要用户名和密码才能登录,但是如果您转换了 USERNAME_FIELD = 'email' 那么现在您无法使用用户名和密码登录,因为您的用户名字段已转换为电子邮件.. ..

So Now it will show like this :

如果您尝试创建另一个超级用户,则它不会要求输入用户名,它只会要求输入电子邮件和密码,然后仅在您尝试登录管理面板时通过电子邮件和密码创建超级用户后,它才会抛出该错误因为没有任何用户名和用户名字段是必需的 Error while creating superuser

2:这就是为什么在迁移期间创建自定义用户模型后会抛出错误的原因 解决它首先在您的设置中添加 AUTH_USER_MODEL = 'appname.custommodelname'(appname 是您定义自定义用户模型的应用程序名称,自定义模型名称是您提供给自定义用户模型的模型名称)。 py 3:然后删除您创建该自定义用户模型的该应用程序的迁移文件夹,然后删除该项目的数据库 db.sqlite3 4:现在运行migrations python manage.py makemigrations appname(您定义自定义用户模型的那个应用程序名称) 5:然后通过 python manage.py migrate 进行迁移 6:大功告成

答案 20 :(得分:0)

好吧,在做任何奇怪的事情或核问题之前,请先删除数据库并重建它。

如果使用POsgres-

DROP SCHEMA public CASCADE;
CREATE SCHEMA PUBLIC;

然后重新进行迁移

./manage.py migrate

这是最基本的解决方案,通常可以解决问题。除非绝对必要,否则不要重新构建迁移。

答案 21 :(得分:0)

首先备份您的数据。 (复制您的数据库文件)。

删除sqlite.db以及迁移文件夹

然后,运行以下命令:

./manage.py makemigrations APP_NAME
./manage.py migrate APP_NAME

在删除数据库文件和迁移文件夹后,请确保在迁移命令后写应用程序名称。

答案 22 :(得分:0)

如果在初始迁移后扩展用户模型,此问题通常会出现。因为无论何时扩展Abstract用户,它都会创建模型中显示的基本字段,例如电子邮件,名字等。

即使这适用于Django中的任何抽象模型。

为此,一个非常简单的解决方案是创建一个新数据库然后应用迁移或删除 [在这种情况下,您将删除所有数据。] 并重新应用迁移。

答案 23 :(得分:0)

您的错误本质上是:

Migration "B" is applied before its dependency "A" on database 'default'.

完整性检查:首先,打开数据库并查看“ django_migrations”表中的记录。记录应按时间顺序列出(例如:A,B,C,D ...)。

确保错误中列出的“ A”迁移的名称与数据库中列出的“ A”迁移的名称匹配。 (如果您之前,手动,已编辑,删除或重命名了迁移文件,则它们可能会有所不同)

要解决此问题,请在数据库中重命名迁移A.或重命名文件名。但是请确保所做的更改与您团队中其他开发人员的数据库中的内容匹配(或所做的更改与您的生产数据库中的内容匹配)

答案 24 :(得分:0)

除了用户错误外,还有另一个原因可能导致这种问题:a known issue with Django涉及压缩的迁移。

我们进行了一系列迁移,这些迁移在Python 2.7 + Django 1.11中运行良好。即使重新创建数据库时,运行makemigrationsmigrate仍然可以正常工作,依此类推,甚至(出于测试目的)。

但是,当我们将项目移至Python 3.6(当前使用相同的Django 1.11)时,我一直试图找出为什么相同的迁移仅在首次运行时才适用的问题。之后,任何尝试运行makemigrations甚至只是运行migrate都会导致错误:

django.db.migrations.exceptions.InconsistentMigrationHistory

其中迁移foo.0040-thing在其依赖项foo.0038-something-squashed-0039-somethingelse之前应用(我们只是碰巧一次压缩了迁移,其余的则更为简单)。

让我烦恼了一阵子的原因是为什么这只会在Python 3上发生。如果数据库确实不一致,那么这应该一直在发生。迁移在首次应用时似乎运行良好,同样令人困惑。

经过大量搜索(包括当前的问答线程),我偶然发现了the aforementioned Django bug report。我们的南瓜迁移确实确实在b行中使用了replaces前缀(例如replaces = [(b'', 'foo.0038-defunct'),.......]

一旦我从b行中删除了replaces前缀,它就可以正常工作。

答案 25 :(得分:0)

创建新项目且没有任何应用程序时,您将运行

python manage.py migrate

Django默认会创建10个表。

如果您要在此之后创建从AbstractUser继承的客户用户模型,则会遇到以下问题,如下所示:

  

django.db.migrations.exceptions.InconsistentMigrationHistory:   迁移admin.0001_initial在其依赖项之前应用   account.0001_initial在数据库“默认”上。

最后, 我删除了整个数据库并运行

答案 26 :(得分:0)

如果在您尝试创建自己的用户模型而非标准时显示该异常,请按照instruction的说明进行操作 我已经逐步按照说明解决了我的问题:

  
      
  1. 创建与auth.User相同的自定义用户模型,将其命名为User(所以   多对多表保持相同的名称)并设置db_table =&#39; auth_user&#39;   (所以它使用相同的表格)
  2.   
  3. 丢弃所有迁移
  4.   
  5. 重新创建一组新的迁移
  6.   
  7. 如果你感到焦虑,可以牺牲一只鸡,也许两只;还可以备份数据库
  8.   
  9. 截断django_migrations表
  10.   
  11. 伪造 - 应用新的迁移集
  12.   
  13. 取消设置db_table,对自定义模型进行其他更改,生成迁移并应用它们
  14.         

    强烈建议在强制执行的数据库上执行此操作   外键约束。不要在笔记本电脑上尝试使用SQLite   期望它能在服务器上运行Postgres!

答案 27 :(得分:0)

首先删除所有迁移和db.sqlite3文件,然后按照以下步骤操作:

$ ./manage.py makemigrations myapp 
$ ./manage.py squashmigrations myapp 0001(may be differ)

删除旧的迁移文件,最后删除。

$ ./manage.py migrate