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
等于您的应用名称的行。
然后执行makemigrations
和migrate
即可。
【讨论】:
这比创建手动迁移的公认答案更方便 如果迁移中的应用之间存在依赖关系,这可能会很危险。 这对我很有效,谢谢。我还必须从 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
中的注释代码以及views
、signals
等中的所有这些模型用法(以防止错误)。
python manage.py makemigrations YOUR_APP_NAME
python manage.py migrate --fake
取消评论您在第 3 步中评论的内容
python manage.py makemigrations YOUR_APP_NAME
迁移不带--fake:python 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 迁移不会重新创建删除的表,为啥?的主要内容,如果未能解决你的问题,请参考以下文章