好吧,我正在关注 official documentation 上的 Django 2.0 教程。 当我意识到我将模型命名为“问题”而不是“问题”时。 (我是 Django 新手)
我已经这么做了
$ python manage.py makemigrations polls
$ python manage.py migrate
所以我想我可以重复这个来应用更改。
Django 问我是否要重命名,所以我说是。
(venv) H:\PycharmProjects\django_tutorials\mysite>python manage.py makemigrations
Did you rename the polls.Questions model to Question? [y/N] y
Migrations for 'polls':
polls\migrations\0002_auto_20180804_0935.py
- Rename model Questions to Question
但是当我尝试迁移时,Django 不会运行迁移并向我显示此错误。
(venv) H:\PycharmProjects\django_tutorials\mysite>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Applying polls.0001_initial... OK
Applying polls.0002_auto_20180804_0935...Traceback (most recent call last):
File "manage.py", line 15, in <module>
execute_from_command_line(sys.argv)
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from_command_line
utility.execute()
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\core\management\__init__.py", line 375, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\core\management\base.py", line 316, in run_from_argv
self.execute(*args, **cmd_options)
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\core\management\base.py", line 353, in execute
output = self.handle(*args, **options)
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\core\management\base.py", line 83, in wrapped
res = handle_func(*args, **kwargs)
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\core\management\commands\migrate.py", line 203, in handle
fake_initial=fake_initial,
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\db\migrations\executor.py", line 117, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\db\migrations\executor.py", line 147, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\db\migrations\executor.py", line 244, in apply_migration
state = migration.apply(state, schema_editor)
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\db\migrations\migration.py", line 124, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\db\migrations\operations\models.py", line 330, in database_forwards
new_model._meta.db_table,
File "H:\PycharmProjects\django_tutorials\venv\lib\site-packages\django\db\backends\sqlite3\schema.py", line 84, in alter_db_table
) % old_db_table)
django.db.utils.NotSupportedError: Renaming the 'polls_questions' table while in a transaction is not supported on SQLite because it would break referential integrity. Try adding `atomic = False` to the Migration class.
我用谷歌搜索并one Stackoverflow question说我应该添加 atomic=False
但他从未解释原因。
我还用谷歌搜索了official documentation对于“非原子迁移”,但仍然不明白为什么需要简单的模型名称更改。 (说实话,我很难理解这是什么。)
真的应该这样改型号吗?我做错了什么吗?
Non-atomic migrations
On databases that support DDL transactions (SQLite and PostgreSQL), migrations will run inside a transaction by default. For use cases such as performing data migrations on large tables, you may want to prevent a migration from running in a transaction by setting the atomic attribute to False:
最佳答案
TL;DR
您可以在 SQLite 中设置atomic=False
或使用 PostgreSQL、MySQL
进行原子表重命名。
详细信息
也许您已经知道,此错误是在 django\db\backends\sqlite3\schema.py", line 84, in alter_db_table
如果你想知道为什么可以看这段代码。 (这将覆盖 base/schema.py
)https://github.com/django/django/blob/master/django/db/backends/sqlite3/schema.py#L77
def alter_db_table(self, model, old_db_table, new_db_table, disable_constraints=True):
if disable_constraints and self._is_referenced_by_fk_constraint(old_db_table):
if self.connection.in_atomic_block:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # if checked atomic, raise NotSupportedError
raise NotSupportedError((
'Renaming the %r table while in a transaction is not '
'supported on SQLite because it would break referential '
'integrity. Try adding `atomic = False` to the Migration class.'
) % old_db_table)
self.connection.enable_constraint_checking()
super().alter_db_table(model, old_db_table, new_db_table)
self.connection.disable_constraint_checking()
else:
super().alter_db_table(model, old_db_table, new_db_table)
然后您可以比较默认的 Postgresql 或 Mysql(这些不会覆盖 base/schema.py
)https://github.com/django/django/blob/master/django/db/backends/base/schema.py#L399
def alter_db_table(self, model, old_db_table, new_db_table):
"""Rename the table a model points to."""
if (old_db_table == new_db_table or
(self.connection.features.ignores_table_name_case and
old_db_table.lower() == new_db_table.lower())):
return
self.execute(self.sql_rename_table % {
"old_table": self.quote_name(old_db_table),
"new_table": self.quote_name(new_db_table),
})
# Rename all references to the old table name.
for sql in self.deferred_sql:
if isinstance(sql, Statement):
sql.rename_table_references(old_db_table, new_db_table)
摘要
Django 的 Sqlite3 不允许使用重命名表的原子选项。
您可以使用 Django 的 Postgresql、Mysql 等(允许原子表重命名)。
关于python - 为什么在 Django 中更改模型名称时必须声明 'atomic=False'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51681660/