Django 不会让我 运行 迁移,因为检查功能检测到对我正在添加的新字段的引用
Django won't let me run migrate because the check function detects references to a new field I am adding
我正在向模型添加一个新字段,但我无法使迁移正常工作
sqlite3.OperationalError: no such column: main_language.iso639_1
我只能通过在我的代码中注释掉对新字段的所有引用来使用 makemigration 生成迁移文件,但现在我无法 运行 在不保留该字段注释掉的情况下进行迁移。
这是不可接受的,因为引用我的新字段显然需要最终出现在我的代码中,并且拉取最新版本代码库的任何其他人在尝试 运行 迁移时将拥有未注释的代码。
尽管多次向模型添加新字段,但我以前没有遇到过这个问题,不知道这次为什么会这样:
# iso639_1 is the new field
class Language(TranslatableMixin, models.Model):
ENGLISH = 1 # id for English should always be 1
ISO_HELP_TEXT = _("Please find the correct code at: https://www.loc.gov/standards/iso639-2/php/code_list.php")
title = models.ForeignKey('main.Sentence', on_delete=models.PROTECT, related_name='LanguageTitle')
iso639_2 = models.CharField(max_length=8, help_text=ISO_HELP_TEXT)
iso639_1 = models.CharField(max_length=8, blank=True, default='', help_text=ISO_HELP_TEXT)
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
created = models.DateTimeField(auto_now_add=True)
objects = LanguageManager()
尝试 运行 'python manage.py migrate':
时收到错误
Traceback (most recent call last):
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\sqlite3\base.py", line 303, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: no such column: main_language.iso639_1
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Win7\OneDrive\Programming\Git\lang\manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\__init__.py", line 371, in execute_from_command_line
utility.execute()
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\__init__.py", line 365, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\base.py", line 288, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\base.py", line 332, in execute
self.check()
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\base.py", line 364, in check
include_deployment_checks=include_deployment_checks,
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\commands\migrate.py", line 58, in _run_checks
issues.extend(super()._run_checks(**kwargs))
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\base.py", line 351, in _run_checks
return checks.run_checks(**kwargs)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\checks\registry.py", line 73, in run_checks
new_errors = check(app_configs=app_configs)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\checks\urls.py", line 13, in check_url_config
return check_resolver(resolver)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\checks\urls.py", line 23, in check_resolver
return check_method()
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\urls\resolvers.py", line 399, in check
for pattern in self.url_patterns:
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\utils\functional.py", line 36, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\urls\resolvers.py", line 540, in url_patterns
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\utils\functional.py", line 36, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\urls\resolvers.py", line 533, in urlconf_module
return import_module(self.urlconf_name)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\importlib\__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 678, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "C:\Users\Win7\OneDrive\Programming\Git\lang\lang\urls.py", line 3, in <module>
from lang import views as core_views
File "C:\Users\Win7\OneDrive\Programming\Git\lang\lang\views.py", line 9, in <module>
from main.views import background_tasks
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\views\__init__.py", line 1, in <module>
from .assess import *
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\views\assess.py", line 6, in <module>
from .main import move_to_next_mode
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\views\main.py", line 4, in <module>
from main.forms import SignUpCourseForm, SelectClassForm
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\forms.py", line 25, in <module>
class InviteDetailsForm(forms.Form):
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\forms.py", line 36, in InviteDetailsForm
label = _('Which language should the invitation email be sent in?'),
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\forms\fields.py", line 758, in __init__
self.choices = choices
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\forms\fields.py", line 775, in _set_choices
value = list(value)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\models\query.py", line 272, in __iter__
self._fetch_all()
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\models\query.py", line 1179, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\models\query.py", line 53, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\models\sql\compiler.py", line 1068, in execute_sql
cursor.execute(sql, params)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 100, in execute
return super().execute(sql, params)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\sqlite3\base.py", line 303, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such column: main_language.iso639_1
Finished "C:\Users\Win7\OneDrive\Programming\Git\lang\manage.py migrate" execution.
LanguageManager 中存在引发错误的代码..
class LanguageManager(models.Manager):
def interface_language_choices(self):
localizations = [x[0] for x in settings.LANGUAGES]
return Language.objects.filter(iso639_1__in=localizations)
如果我注释掉 def interface_language_choices(self) 的主体,用 pass 替换它,我就会得到与未给出 return 值的函数相关的错误。为什么它甚至坚持 运行ning 我的代码只是为了进行迁移?
我的迁移文件:
from django.db import migrations, models
def populate_iso(apps, schema_editor):
Language = apps.get_model('main', 'Language')
for x in (('eng','en'),('tur','tr'),('rus','ru'),('fra','fr'),('uzb','uz'),('spa','es')):
L = Language.objects.get(iso639_2=x[0])
L.iso639_1 = x[1]
L.save()
class Migration(migrations.Migration):
dependencies = [
('main', '0030_auto_20180620_1649'),
]
operations = [
migrations.AddField(
model_name='language',
name='iso639_1',
field=models.CharField(blank=True, default='', help_text='Please find the correct code at: https://www.loc.gov/standards/iso639-2/php/code_list.php', max_length=8),
),
migrations.RunPython(populate_iso),
]
来自 the FineManual:
Migrations that alter data are usually called “data migrations”; they’re best written as separate migrations, sitting alongside your schema migrations.
IOW:将您的迁移分成两部分 - 第一个添加字段,第二个用相关数据填充它。
但是这其实不是你的问题。从你的回溯:
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\forms.py", line 25, in <module>
class InviteDetailsForm(forms.Form):
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\forms.py", line 36, in InviteDetailsForm
label = _('Which language should the invitation email be sent in?'),
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\forms\fields.py", line 758, in __init__
self.choices = choices
您的 InviteDetailsForm
代码显然在 class 顶级 进行数据库查询 以填充字段的选择 - 我假设如下:
class InviteDetailsForm(forms.Form):
# ...
something = forms.ChoiceField(
choice= Language.objects.interface_languages_choices()
# ...
)
这段代码在导入模块时执行(这是正常的 Python 操作 - class
是可执行语句),这导致了您的问题。解决方法是pass the method itself instead of passing it's result:
something = forms.ChoiceField(
# notice the absence of parens !
choice= Language.objects.interface_languages_choices,
# ...
)
或者使用 ModelChoiceField
而不是 ChoiceField
(前者不会强制对查询集求值,而第二个会)。
Why is it even insisting on running my code just to do a migration
因为 "it" 需要加载应用程序和模型以及 url confs,它导入视图,导入你的表单模块,它在你的表单顶层执行代码 class,它调用你的方法。
我正在向模型添加一个新字段,但我无法使迁移正常工作
sqlite3.OperationalError: no such column: main_language.iso639_1
我只能通过在我的代码中注释掉对新字段的所有引用来使用 makemigration 生成迁移文件,但现在我无法 运行 在不保留该字段注释掉的情况下进行迁移。
这是不可接受的,因为引用我的新字段显然需要最终出现在我的代码中,并且拉取最新版本代码库的任何其他人在尝试 运行 迁移时将拥有未注释的代码。
尽管多次向模型添加新字段,但我以前没有遇到过这个问题,不知道这次为什么会这样:
# iso639_1 is the new field
class Language(TranslatableMixin, models.Model):
ENGLISH = 1 # id for English should always be 1
ISO_HELP_TEXT = _("Please find the correct code at: https://www.loc.gov/standards/iso639-2/php/code_list.php")
title = models.ForeignKey('main.Sentence', on_delete=models.PROTECT, related_name='LanguageTitle')
iso639_2 = models.CharField(max_length=8, help_text=ISO_HELP_TEXT)
iso639_1 = models.CharField(max_length=8, blank=True, default='', help_text=ISO_HELP_TEXT)
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
created = models.DateTimeField(auto_now_add=True)
objects = LanguageManager()
尝试 运行 'python manage.py migrate':
时收到错误Traceback (most recent call last):
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\sqlite3\base.py", line 303, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: no such column: main_language.iso639_1
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Win7\OneDrive\Programming\Git\lang\manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\__init__.py", line 371, in execute_from_command_line
utility.execute()
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\__init__.py", line 365, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\base.py", line 288, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\base.py", line 332, in execute
self.check()
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\base.py", line 364, in check
include_deployment_checks=include_deployment_checks,
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\commands\migrate.py", line 58, in _run_checks
issues.extend(super()._run_checks(**kwargs))
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\management\base.py", line 351, in _run_checks
return checks.run_checks(**kwargs)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\checks\registry.py", line 73, in run_checks
new_errors = check(app_configs=app_configs)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\checks\urls.py", line 13, in check_url_config
return check_resolver(resolver)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\core\checks\urls.py", line 23, in check_resolver
return check_method()
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\urls\resolvers.py", line 399, in check
for pattern in self.url_patterns:
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\utils\functional.py", line 36, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\urls\resolvers.py", line 540, in url_patterns
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\utils\functional.py", line 36, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\urls\resolvers.py", line 533, in urlconf_module
return import_module(self.urlconf_name)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\importlib\__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 678, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "C:\Users\Win7\OneDrive\Programming\Git\lang\lang\urls.py", line 3, in <module>
from lang import views as core_views
File "C:\Users\Win7\OneDrive\Programming\Git\lang\lang\views.py", line 9, in <module>
from main.views import background_tasks
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\views\__init__.py", line 1, in <module>
from .assess import *
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\views\assess.py", line 6, in <module>
from .main import move_to_next_mode
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\views\main.py", line 4, in <module>
from main.forms import SignUpCourseForm, SelectClassForm
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\forms.py", line 25, in <module>
class InviteDetailsForm(forms.Form):
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\forms.py", line 36, in InviteDetailsForm
label = _('Which language should the invitation email be sent in?'),
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\forms\fields.py", line 758, in __init__
self.choices = choices
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\forms\fields.py", line 775, in _set_choices
value = list(value)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\models\query.py", line 272, in __iter__
self._fetch_all()
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\models\query.py", line 1179, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\models\query.py", line 53, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\models\sql\compiler.py", line 1068, in execute_sql
cursor.execute(sql, params)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 100, in execute
return super().execute(sql, params)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\db\backends\sqlite3\base.py", line 303, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such column: main_language.iso639_1
Finished "C:\Users\Win7\OneDrive\Programming\Git\lang\manage.py migrate" execution.
LanguageManager 中存在引发错误的代码..
class LanguageManager(models.Manager):
def interface_language_choices(self):
localizations = [x[0] for x in settings.LANGUAGES]
return Language.objects.filter(iso639_1__in=localizations)
如果我注释掉 def interface_language_choices(self) 的主体,用 pass 替换它,我就会得到与未给出 return 值的函数相关的错误。为什么它甚至坚持 运行ning 我的代码只是为了进行迁移?
我的迁移文件:
from django.db import migrations, models
def populate_iso(apps, schema_editor):
Language = apps.get_model('main', 'Language')
for x in (('eng','en'),('tur','tr'),('rus','ru'),('fra','fr'),('uzb','uz'),('spa','es')):
L = Language.objects.get(iso639_2=x[0])
L.iso639_1 = x[1]
L.save()
class Migration(migrations.Migration):
dependencies = [
('main', '0030_auto_20180620_1649'),
]
operations = [
migrations.AddField(
model_name='language',
name='iso639_1',
field=models.CharField(blank=True, default='', help_text='Please find the correct code at: https://www.loc.gov/standards/iso639-2/php/code_list.php', max_length=8),
),
migrations.RunPython(populate_iso),
]
来自 the FineManual:
Migrations that alter data are usually called “data migrations”; they’re best written as separate migrations, sitting alongside your schema migrations.
IOW:将您的迁移分成两部分 - 第一个添加字段,第二个用相关数据填充它。
但是这其实不是你的问题。从你的回溯:
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\forms.py", line 25, in <module>
class InviteDetailsForm(forms.Form):
File "C:\Users\Win7\OneDrive\Programming\Git\lang\main\forms.py", line 36, in InviteDetailsForm
label = _('Which language should the invitation email be sent in?'),
File "C:\Users\Win7\OneDrive\Programming\Git\lang\.venv\lib\site-packages\django\forms\fields.py", line 758, in __init__
self.choices = choices
您的 InviteDetailsForm
代码显然在 class 顶级 进行数据库查询 以填充字段的选择 - 我假设如下:
class InviteDetailsForm(forms.Form):
# ...
something = forms.ChoiceField(
choice= Language.objects.interface_languages_choices()
# ...
)
这段代码在导入模块时执行(这是正常的 Python 操作 - class
是可执行语句),这导致了您的问题。解决方法是pass the method itself instead of passing it's result:
something = forms.ChoiceField(
# notice the absence of parens !
choice= Language.objects.interface_languages_choices,
# ...
)
或者使用 ModelChoiceField
而不是 ChoiceField
(前者不会强制对查询集求值,而第二个会)。
Why is it even insisting on running my code just to do a migration
因为 "it" 需要加载应用程序和模型以及 url confs,它导入视图,导入你的表单模块,它在你的表单顶层执行代码 class,它调用你的方法。