编辑: 我通过数据库删除了,从头开始迁移时会发生这种情况,所以我的基本迁移顺序似乎有问题。
基本上我已经(步骤 1 实际上是步骤 14,但是有)
创建模型
用夹具填充模型
向模型添加新列
当执行到第 2 步时,它会因“列不存在”错误而终止。
此时数据库没有该列,它所应用的夹具也没有对其进行任何引用。
也许这遗漏了一些关键细节并暴露了我对 django 的相对陌生,但我试图将我的问题隔离到最少的步骤来重现问题。
启动状态:应用程序运行良好,测试全部通过。
新状态:应用程序运行良好,运行测试会产生错误。
Creating test database for alias 'default'...
Found 23 test(s).
Installed 5 object(s) from 1 fixture(s)
Traceback (most recent call last):
File "/home/f/.virtualenvs/mgmt/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
return self.cursor.execute(sql, params)
File "/home/f/.virtualenvs/mgmt/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 357, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: no such column: recommended_for_text
recommend_for_text 是新列的名称。
recommended_for_text = models.CharField(null=True, blank=True, max_length=256)
它按预期显示在应用程序的我的视图中,只是运行测试就给我带来了问题。
更新: 更改之前运行测试输出:
Found 23 test(s).
Creating test database for alias 'default'...
Installed 5 object(s) from 1 fixture(s)
Installed 9 object(s) from 1 fixture(s)
System check identified no issues (0 silenced).
.......................
----------------------------------------------------------------------
Ran 23 tests in 2.286s
OK
Destroying test database for alias 'default'...
及之后:
Found 23 test(s).
Creating test database for alias 'default'...
Installed 5 object(s) from 1 fixture(s)
Traceback (most recent call last):
File "/home/f/.local/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
return self.cursor.execute(sql, params)
File "/home/f/.local/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 357, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: no such column: recommended_for_text
0016_migration.py:
# Generated by Django 4.1.13 on 2024-04-25 17:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("sites", "0015_populate_plans"),
]
operations = [
migrations.AddField(
model_name="plan",
name="recommended_for_text",
field=models.CharField(blank=True, max_length=256, null=True),
),
]
0015_migration.py:(我认为这一定是失败的原因,但在添加新列和0016之前它可以工作)
# Generated by Django 4.1.10 on 2024-04-03 14:02
from django.core.management import call_command
from django.db import migrations
def load_plans(apps, schema_editor):
call_command('loaddata', 'plans.json', app_label='sites')
class Migration(migrations.Migration):
dependencies = [
("sites", "0014_sitecommandlog_note"),
]
operations = [
migrations.RunPython(load_plans),
]
plans.json 有一堆这样的记录(特别是没有Recommended_for_text 字段,因为它还不存在)
{
"model": "sites.plan",
"pk": 2,
"fields": {
"portal_plan_name": "Basic",
"plan_sku": "plan-basic_small-contract-annual-1",
"traffic_limits": "35000",
"annual_plan_charge": "224.00",
"is_active": true
}
}
更奇怪的是我尝试从tests.py中消除实际测试 这运行得很好
from unittest import main
from django.test import TestCase
if __name__ == '__main__':
main()
但这会引发 no such columns 异常
from unittest import main
from django.test import TestCase
class SleepTest(TestCase):
def test_sleep(self):
from time import sleep
sleep(10)
if __name__ == '__main__':
main()
你的
0015_migration
很有问题。根据经验,您不应在迁移中调用 loaddata
命令,因为它将使用当前模型而不是 历史模型,这意味着当您仅添加迁移时,迁移可能会起作用,但可能会失败未来当模型发生更多变化时。
现在您可以执行以下操作:
在
0015_migration
中将 load_plans
的参数中的 RunPython
替换为 RunPython.noop
:
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("sites", "0014_sitecommandlog_note"),
]
operations = [
migrations.RunPython(migrations.RunPython.noop),
]
接下来,如果您真的想使用
loaddata
命令,请从迁移系统外部进行操作。如果您确实想通过迁移加载数据,请考虑进行不依赖于 loaddata
命令的数据迁移。如果您想通过数据迁移加载固定装置,您可以按照此问题中的指导来模拟
loaddata
的作用:使用 Django 1.7+ 和数据迁移加载初始数据