Django 1.7 迁移不会重新创建删除的表,为啥?

Posted

技术标签:

【中文标题】Django 1.7 迁移不会重新创建删除的表,为啥?【英文标题】:Django 1.7 migrations won't recreate a dropped table, why?Django 1.7 迁移不会重新创建删除的表,为什么? 【发布时间】:2014-12-30 01:11:26 【问题描述】:

使用 Django 1.7 迁移。

我不小心在我的数据库中删除了一个表。我假设通过再次运行迁移,这将重新创建表,但没有,Django 声明“没有要应用的迁移”。

如何让 Django 重新创建表?

我已经跑了:

> makemigrations - No changes detected
> migrate - No migrations to apply.

我尝试对模型进行更改并运行新的迁移,它只是说“表'x.test_customer'不存在”这是正确的,但我希望它会重新创建表.

【问题讨论】:

Django 开发人员真的把过去很简单的syncdb 搞砸了。 【参考方案1】:

转到您的数据库并找到表django_migrations。删除所有app 等于您的应用名称的行。

然后执行makemigrationsmigrate 即可。

【讨论】:

这比创建手动迁移的公认答案更方便 如果迁移中的应用之间存在依赖关系,这可能会很危险。 这对我很有效,谢谢。我还必须从 django_content_type 中删除 app_label = 'yourappname' 并从 auth_permission 中删除,其中 content_type_id = 之前删除的行之一。【参考方案2】:

我找到的另一种解决方案,效果很好:

在 django 1.7 中:

    删除您的迁移文件夹

    在数据库中:DELETE FROM django_migrations WHERE app = 'app_name'

    您也可以截断此表。

    python manage.py makemigrations

    python manage.py migrate --fake

在 django 1.9.5 中:

    删除您的迁移文件夹

    在数据库中:DELETE FROM django_migrations WHERE app = 'app_name'

    您也可以截断此表。

    python manage.py makemigrations app_name

    python manage.py migrate

这对我来说 100% 有效!

【讨论】:

工作得很好,必须从 django_migrations 中删除,它会工作得很好【参考方案3】:

迁移检查模型中的差异,然后将其转换为操作,然后再转换为 SQL。它不会自动将 db 方案与您的模型同步,并且它无法知道您删除了一个表(它不知道手动更改,因为您不应该这样做手动更改。这就是重点)

答案?手动更改也需要手动迁移。您需要做的只是编写自己的迁移并手动告诉南重新构建表。这不是很困难,The docs 让它变得很容易。做这样的事情:

from django.db import migrations, models

class Migration(migrations.Migration):

    operations = [
        migrations.CreateModel("Foo"),
        migrations.AddField("Foo", "bar", models.IntegerField(default=0))
    ] 

您可能可以查看第一个迁移文件(最初制作模型的文件)并复制粘贴几乎所有文件。然后你所要做的就是像往常一样运行迁移

【讨论】:

我明白了,现在说得通了。 这也行吗? ***.com/questions/25606879/…。删除后,您可以从迁移历史记录中尝试再次执行 makemigrations/migrate。我不知道当表已经被删除时这是否会崩溃...... @djangozone 请注意,这会清除并删除所有表(如果它是没有重要数据的开发人员,这也可以) 是的,我通常使用 dumpdata/loaddata 组合,在我看来这比处理手动迁移更简单。Ofc,如果你处理大量数据,这不是最好的方法,但不是我的案例。 很高兴知道!很高兴有帮助 =] @djangozone 真的真的取决于项目(以及个人喜好)。我认为迁移非常简单,但是当事情变得混乱时,我有时也会选择完全重置【参考方案4】:

我实际上找到了一种更简单的方法来做到这一点。您假装回滚不存在的内容,然后重新迁移。如果您的迁移 0005 是它创建表的位置:

python manage.py migrate myapp --fake 0004
python manage.py migrate myapp

之后应该会很好!

如果你需要跳过后面的,你可以这样做:

python manage.py migrate myapp --fake 0004
python manage.py migrate myapp 0005
python manage.py migrate myapp --fake

之后应该会很好!

【讨论】:

对于较新版本的 django,命令应为 python manage.py migrate --fake myapp 0004,其中应用名称是 --fake 标志的参数【参考方案5】:

django 2.0.2 的情况下,为了重新创建删除的表,我需要在myapp 中注释我的模型,然后使用--fake 迁移并取消注释我的模型并迁移不使用--fake 与劳尔回答略有不同:

    删除所需应用中的迁移文件 感谢 raul 回答:在数据库中:DELETE FROM django_migrations WHERE app = 'app_name'models.py 中的注释代码以及viewssignals 等中的所有这些模型用法(以防止错误)。 python manage.py makemigrations YOUR_APP_NAME python manage.py migrate --fake 取消评论您在第 3 步中评论的内容 python manage.py makemigrations YOUR_APP_NAME 迁移不带--fakepython manage.py migrate

这应该可以解决一些用户问题。

【讨论】:

【参考方案6】:

完全免责声明,在某些情况下这是一种破坏性操作,我主要使用它来重新迁移系统的某些部分而不影响数据库。

您是否尝试通过django_migrations 表进行操作?只需删除映射到应用标签和相关迁移名称的行并删除这些行。

+----+-----------------------+----------------------------------------------------------+---------------------+
| id | app                   | name                                                     | applied             |
+----+-----------------------+----------------------------------------------------------+---------------------+
|  1 | contenttypes          | 0001_initial                                             | 2015-03-07 16:32    |
| 30 | homepage              | 0001_initial                                             | 2015-04-02 13:30:44 |
| 31 | homepage              | 0002_auto_20150408_1751                                  | 2015-04-08 12:24:55 |
| 32 | homepage              | 0003_remove_mappinghomepagemoduleinventory_inventoryinfo | 2015-04-09 08:09:59 |
+----+-----------------------+----------------------------------------------------------+---------------------+

所以现在如果我想删除 homepage,我可以删除第 30、31、32 行。

当然,由于您也删除了表格,因此您也需要更改 django_content_type

+----+----------------------------------------+-----------------------+--------------------------------------+
| id | name                                   | app_label             | model                                |
+----+----------------------------------------+-----------------------+--------------------------------------+
|  1 | content type                           | contenttypes          | contenttype                          |
|  2 | session                                | sessions              | session                              |
|  3 | site                                   | sites                 | site                                 |
| 92 | master_homepagemodule_extrafields      | homepage              | masterhomepagemoduleextrafields      |
| 93 | mapping_homepagemodule_inventory       | homepage              | mappinghomepagemoduleinventory       |
| 94 | master_homepagemodule_inventoryfields  | homepage              | masterhomepagemoduleinventoryfields  |
| 95 | mapping_homepagemodule_inventoryfields | homepage              | mappinghomepagemoduleinventoryfields |
| 96 | master_homepagemodule                  | homepage              | masterhomepagemodule                 |
| 97 | mapping_homepagemodule_extrafields     | homepage              | mappinghomepagemoduleextrafields     |
+----+----------------------------------------+-----------------------+--------------------------------------+

因此,现在您必须删除需要重新迁移的表,方法是删除这些表的行。

我在时间紧缺并且我们需要快速修复或在开发中玩耍时使用此功能。 希望对你也有帮助!

【讨论】:

感谢提供这个肮脏的修复,它有帮助。在开发阶段,删除了一个表,然后就回不去了。删除 django_migrations 中的相关行后,我运行“python manage.py migrate zero”来清理/删除所有表,然后运行“python manage.py migrate”重新开始。【参考方案7】:

在 django >= 1.9 上执行此操作的最简单方法是运行以下命令:

./manage.py migrate app_name zero

这将删除您的表并恢复所有迁移。

【讨论】:

【参考方案8】:

在构建一个学习 django 的小应用程序时遇到了这个问题。我想为现有表创建一个非空列。分为三个步骤:

    删除表 删除 django_migrations 中的记录 删除有问题的表的迁移 如果您在此步骤之前运行“python manage.py makemigrations posts”,您仍然会收到“您正在尝试添加一个不可为空的字段”

对于实际应用程序,您需要像其他人指出的那样提供默认值。

【讨论】:

【参考方案9】:

好的,所以我所做的就是不要搞乱迁移。似乎我经常在迁移中遇到麻烦。在这种情况下,尝试重播迁移让我一事无成。可能没有帮助,因为有一些南方复古迁移以及较新的 1.7 东西。

环境:postgres 9.3

基本上,我将数据库的旧备份恢复到空数据库。然后我在 postgres 管理实用程序中调出恢复目标,并从每个表的描述中复制/粘贴创建表(我只有 4 个可用)。切换到我的测试数据库并在 pg 的 sql 实用程序中运行它。

我不知道,如果您遇到问题(在我看来,好像我的 id 字段的序列不起作用),我认为手动删除表是不合理的,只要您可以忍受丢失您的表数据。在该用例中,迁移应该具有弹性。

【讨论】:

【参考方案10】:

可能是最简单的方法。

    复制您要迁移的迁移文件并将其重命名为最新的迁移文件

例如如果你要迁移的文件是app_name.002_xyz,而你最新的迁移文件是app_name.004_abc

然后您需要复制app_name.002_xyz 并将其重命名为最新的迁移文件。比如我们把它重命名为app_name.005_xyz

    现在在这个新文件中添加最近最新的作为依赖项

例如将此行添加到新的迁移文件中

class Migration(migrations.Migration):

    dependencies = [
        ('app_name', 'app_name.004_abc'),
    ]
    
    ...
    迁移它

例如将此行添加到新的迁移文件中

python manage.py migrate app_name
    太棒了,进行了新的迁移并重新创建了表

例如

Running migrations:
Applying app_name.005_xyz...OK
    删除新的迁移文件app_name.005_xyz,一切顺利!

【讨论】:

以上是关于Django 1.7 迁移不会重新创建删除的表,为啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 django 1.7 会为字段选择的变化创建迁移?

Django 1.7 - 创建初始迁移

Django 1.7 中的 Django-migrations 检测模型更改,但不会在迁移时应用它们

我的旧项目出现 Django 1.7 迁移问题

Django 1.7 迁移挂起

实体框架手动删除的表不能从EF迁移生成