执行squashmigrations后无法重建Django数据库的问题求助
问题:Django squashmigrations后重建数据库执行migrate/makemigrations报错
我在Django中执行了squashmigrations操作,之后删除数据库从头重建(从GitHub拉取仓库重建项目时也会遇到相同问题)。运行python manage.py makemigrations或python manage.py migrate时出现如下错误:
(venv) meal_plan main python manage.py makemigrations Traceback (most recent call last): File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute return self.cursor.execute(sql, params) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/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 table: meal_plan_recipe The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/Users/enricobonardi/CODING/TESTING/meal_plan/manage.py", line 22, in <module> main() File "/Users/enricobonardi/CODING/TESTING/meal_plan/manage.py", line 18, in main execute_from_command_line(sys.argv) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line utility.execute() File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/core/management/base.py", line 402, in run_from_argv self.execute(*args, **cmd_options) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/core/management/base.py", line 443, in execute self.check() File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/core/management/base.py", line 475, in check all_issues = checks.run_checks( File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/core/checks/registry.py", line 88, in run_checks new_errors = check(app_configs=app_configs, databases=databases) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/core/checks/urls.py", line 42, in check_url_namespaces_unique all_namespaces = _load_all_namespaces(resolver) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/core/checks/urls.py", line 61, in _load_all_namespaces url_patterns = getattr(resolver, "url_patterns", []) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/utils/functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/urls/resolvers.py", line 715, in url_patterns patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/utils/functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/urls/resolvers.py", line 708, in urlconf_module return import_module(self.urlconf_name) File "/Users/enricobonardi/.pyenv/versions/3.10.7/lib/python3.10/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1050, in _gcd_import File "<frozen importlib._bootstrap>", line 1027, in _find_and_load File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 688, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 883, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "/Users/enricobonardi/CODING/TESTING/meal_plan/config/urls.py", line 9, in <module> path("", include("meal_plan.urls", namespace="mealplan")), File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/urls/conf.py", line 38, in include urlconf_module = import_module(urlconf_module) File "/Users/enricobonardi/.pyenv/versions/3.10.7/lib/python3.10/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1050, in _gcd_import File "<frozen importlib._bootstrap>", line 1027, in _find_and_load File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 688, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 883, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "/Users/enricobonardi/CODING/TESTING/meal_plan/meal_plan/urls.py", line 5, in <module> from . import views File "/Users/enricobonardi/CODING/TESTING/meal_plan/meal_plan/views.py", line 11, in <module> from .forms import MealPlanForm, RecipeSimpleForm File "/Users/enricobonardi/CODING/TESTING/meal_plan/meal_plan/forms.py", line 26, in <module> class RecipeSimpleForm(forms.ModelForm): File "/Users/enricobonardi/CODING/TESTING/meal_plan/meal_plan/forms.py", line 38, in RecipeSimpleForm RECIPES = [(x.id, x.title) for x in Recipe.objects.all()] File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/models/query.py", line 394, in __iter__ self._fetch_all() File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/models/query.py", line 1866, in _fetch_all self._result_cache = list(self._iterable_class(self)) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/models/query.py", line 87, in __iter__ results = compiler.execute_sql( File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1398, in execute_sql cursor.execute(sql, params) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 103, in execute return super().execute(sql, params) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 67, in execute return self._execute_with_wrappers( File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers return executor(sql, params, many, context) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 84, in _execute with self.db.wrap_database_errors: File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/utils.py", line 91, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute return self.cursor.execute(sql, params) File "/Users/enricobonardi/CODING/TESTING/meal_plan/venv/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 357, in execute return Database.Cursor.execute(self, query, params) django.db.utils.OperationalError: no such table: meal_plan_recipe (venv) ✘ meal_plan main
meal_plan/models.py代码
from django.conf import settings from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver from django.urls import reverse User = settings.AUTH_USER_MODEL # ---------Stagionality----------# class Month(models.Model): name = models.CharField(max_length=25) class Meta: ordering = ("id",) verbose_name = "mese" verbose_name_plural = "mesi" def __str__(self): return self.name class VegetableItem(models.Model): class Types(models.IntegerChoices): VERDURA = 1 FRUTTA = 2 name = models.CharField(max_length=100) type = models.SmallIntegerField(choices=Types.choices, default=Types.VERDURA) description = models.TextField(blank=True) seasonality = models.ManyToManyField(Month, verbose_name="stagionalità") image = models.ImageField(upload_to="vegetableitems", default="vegetableitems/default.png") class Meta: verbose_name = "alimento stagionale" verbose_name_plural = "alimenti stagionali" def __str__(self): return self.name # ---------END of Stagionality----------# # ---------MealPlan----------# class Day(models.TextChoices): LUNEDI = "LUN", "Lunedì" MARTEDI = "MAR", "Martedì" MERCOLEDI = "MER", "Mercoledì" GIOVEDI = "GIO", "Giovedì" VENERDI = "VEN", "Venerdì" SABATO = "SAB", "Sabato" DOMENICA = "DOM", "Domenica" class Type(models.IntegerChoices): COLAZIONE = 1 SPUNTINO = 2 PRANZO = 3 MERENDA = 4 CENA = 5 class MealPlan(models.Model): title = models.CharField(max_length=100) user = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self) -> str: return self.title class Meta: verbose_name_plural = "mealplan" def get_absolute_url(self): return reverse("mealplan:mealplan_detail", kwargs={"pk": self.pk}) class Meal(models.Model): day = models.CharField(max_length=3, choices=Day.choices, default=Day.LUNEDI, verbose_name="giorno") type = models.IntegerField(choices=Type.choices) mealplan = models.ForeignKey(MealPlan, on_delete=models.CASCADE) class Meta: verbose_name = "pasto" verbose_name_plural = "pasti" def __str__(self) -> str: return f"{self.mealplan} ({self.get_day_display()} - {self.get_type_display()})" class Measure(models.IntegerChoices): ML = 1 G = 2 UNIT = 3 class Recipe(models.Model): title = models.CharField(max_length=100) method = models.TextField(blank=True) meals = models.ManyToManyField(Meal) class Meta: verbose_name = "ricetta" verbose_name_plural = "ricette" def __str__(self) -> str: return self.title class Ingredient(models.Model): name = models.CharField(max_length=100) quantity = models.SmallIntegerField(blank=True) measure = models.IntegerField(choices=Measure.choices, default=Measure.G) recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, null=True) @receiver(post_save, sender=MealPlan) def mealplan_post_save_receiver(sender, instance, created, *args, **kwargs): if created: mealplan = instance days_of_the_week = Meal._meta.get_field("day").choices days = [label for label, day in days_of_the_week] for day in days: for type in range(1, 6): meal = Meal.objects.create(mealplan=mealplan, day=day, type=type) meal.save() # ---------END of MealPlan----------#
我曾按照教程重置原仓库的迁移,但没有效果。
问题根源
错误栈明确指向:在RecipeSimpleForm类定义阶段,代码直接执行了Recipe.objects.all()查询数据库。Django执行makemigrations或migrate时会加载URL配置,进而导入视图、表单,此时数据库还未创建meal_plan_recipe表,导致触发OperationalError。
解决步骤
1. 修复表单的数据库查询时机
不要在类定义阶段直接查询数据库,改用以下两种方式之一:
方式一:使用ModelChoiceField(推荐)
如果是要选择Recipe实例,直接用Django内置的ModelChoiceField,它会自动处理查询集:
# meal_plan/forms.py from django import forms from .models import Recipe class RecipeSimpleForm(forms.ModelForm): # 替换原来的RECIPES和自定义选择字段 recipe = forms.ModelChoiceField( queryset=Recipe.objects.all(), empty_label="请选择食谱", label="食谱" ) class Meta: model = # 你的目标模型 fields = # 字段列表
方式二:在表单__init__方法中动态加载选项
如果必须自定义choices格式,在表单实例化时再查询数据库:
# meal_plan/forms.py from django import forms from .models import Recipe class RecipeSimpleForm(forms.ModelForm): # 先定义字段,不设置choices your_field_name = forms.ChoiceField(choices=[], label="食谱") def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 实例化时才查询数据库 self.fields['your_field_name'].choices = [(x.id, x.title) for x in Recipe.objects.all()] class Meta: model = # 你的目标模型 fields = # 字段列表
2. 重新执行迁移初始化
- 删除数据库文件(如
db.sqlite3) - 删除
meal_plan/migrations/目录下除__init__.py外的所有文件 - 执行命令:
python manage.py makemigrations python manage.py migrate
内容的提问来源于stack exchange,提问作者WEBBOgrafico
相关产品推荐
相关产品推荐

