迁移完成后,Django 2.2 无法序列化默认值
Django 2.2 cannot serialize default values once migration has been done
我有一个被称为外键的模型,on_delete 设置为 SET_DEFAULT。因此,我需要为这个模型提供一个默认项。我创建了一个静态方法来执行此操作。
class ScheduleChoice(models.Model):
"""
This model allows users to define crontab schedules.
"""
label = models.CharField(max_length=256, verbose_name="Label", unique=True)
job_schedule = models.CharField(
max_length=256,
default="0 0 * * *", verbose_name="Crontab"
)
@staticmethod
def get_default_schedule_choice():
"""
Because some models rely on ScheduleChoice and need a default value,
we need to give them a default ScheduleChoice.
"""
try:
choice = ScheduleChoice.objects.get_or_create(
label="Every minute",
job_schedule="* * * * *"
)
except ProgrammingError:
choice = None
return choice
@classmethod
def get_choice_count(cls):
"""
Returns how many schedule choices have been defined.
"""
return len(cls.objects.all())
class Meta:
verbose_name = "schedule choice"
verbose_name_plural = "schedule choices"
def __str__(self):
return self.label
class MyOtherModel(models.Model):
"""
Model using ScheduleChoices.
"""
job_schedule = models.ForeignKey(
"ScheduleChoice",
on_delete=models.SET_DEFAULT,
default=ScheduleChoice.get_default_schedule_choice(),
verbose_name="Schedule"
)
activated = models.BooleanField(default=False, verbose_name="activated")
我能够 运行 进行迁移并顺利迁移。
当我修改我的模型并尝试再次使用 makemigrations 以更新迁移文件时,我的问题就开始了。我收到错误:
ValueError: Cannot serialize: <ScheduleChoice: Every minute>
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/2.2/topics/migrations/#migration-serializing
我尝试申请 ,但没有帮助。为什么 Django 需要序列化我的默认值?为什么它只在第一次迁移成功结束后才这样做?
我总是可以使用 reset_db 进行迁移,但在我的生产环境中是不可接受的。
我该如何解决这个问题?
Django 需要序列化您的模型以便为它们制作迁移文件。因此,它还需要序列化您在模型字段上设置的大部分属性(包括 default
)。目前,您定义了一个方法并直接调用它,而不是提供该方法作为默认方法,您的方法 return 是一个带有 ScheduleChoice
和布尔值的元组。
Django 可以序列化布尔值,但不能序列化模型实例(用于迁移),因此您会得到一个错误,更不用说元组无论如何都会导致错误。您应该 不 调用该方法,而只是将方法作为默认方法传递,而不是 return 实例 return 仅 pk
,理想情况下,此方法应该只是一个函数:
class ScheduleChoice(models.Model):
"""
This model allows users to define crontab schedules.
"""
label = models.CharField(max_length=256, verbose_name="Label", unique=True)
job_schedule = models.CharField(
max_length=256,
default="0 0 * * *", verbose_name="Crontab"
)
@classmethod
def get_choice_count(cls):
"""
Returns how many schedule choices have been defined.
"""
return len(cls.objects.all())
class Meta:
verbose_name = "schedule choice"
verbose_name_plural = "schedule choices"
def __str__(self):
return self.label
def get_default_schedule_choice():
choice, _created = ScheduleChoice.objects.get_or_create(
label="Every minute",
job_schedule="* * * * *"
)
# Why would programming error occur?
return choice.pk # Return the pk
class MyOtherModel(models.Model):
"""
Model using ScheduleChoices.
"""
job_schedule = models.ForeignKey(
"ScheduleChoice",
on_delete=models.SET_DEFAULT,
default=get_default_schedule_choice, # Don't call the function, only pass it
verbose_name="Schedule"
)
activated = models.BooleanField(default=False, verbose_name="activated")
我有一个被称为外键的模型,on_delete 设置为 SET_DEFAULT。因此,我需要为这个模型提供一个默认项。我创建了一个静态方法来执行此操作。
class ScheduleChoice(models.Model):
"""
This model allows users to define crontab schedules.
"""
label = models.CharField(max_length=256, verbose_name="Label", unique=True)
job_schedule = models.CharField(
max_length=256,
default="0 0 * * *", verbose_name="Crontab"
)
@staticmethod
def get_default_schedule_choice():
"""
Because some models rely on ScheduleChoice and need a default value,
we need to give them a default ScheduleChoice.
"""
try:
choice = ScheduleChoice.objects.get_or_create(
label="Every minute",
job_schedule="* * * * *"
)
except ProgrammingError:
choice = None
return choice
@classmethod
def get_choice_count(cls):
"""
Returns how many schedule choices have been defined.
"""
return len(cls.objects.all())
class Meta:
verbose_name = "schedule choice"
verbose_name_plural = "schedule choices"
def __str__(self):
return self.label
class MyOtherModel(models.Model):
"""
Model using ScheduleChoices.
"""
job_schedule = models.ForeignKey(
"ScheduleChoice",
on_delete=models.SET_DEFAULT,
default=ScheduleChoice.get_default_schedule_choice(),
verbose_name="Schedule"
)
activated = models.BooleanField(default=False, verbose_name="activated")
我能够 运行 进行迁移并顺利迁移。
当我修改我的模型并尝试再次使用 makemigrations 以更新迁移文件时,我的问题就开始了。我收到错误:
ValueError: Cannot serialize: <ScheduleChoice: Every minute> There are some values Django cannot serialize into migration files. For more, see https://docs.djangoproject.com/en/2.2/topics/migrations/#migration-serializing
我尝试申请
我总是可以使用 reset_db 进行迁移,但在我的生产环境中是不可接受的。
我该如何解决这个问题?
Django 需要序列化您的模型以便为它们制作迁移文件。因此,它还需要序列化您在模型字段上设置的大部分属性(包括 default
)。目前,您定义了一个方法并直接调用它,而不是提供该方法作为默认方法,您的方法 return 是一个带有 ScheduleChoice
和布尔值的元组。
Django 可以序列化布尔值,但不能序列化模型实例(用于迁移),因此您会得到一个错误,更不用说元组无论如何都会导致错误。您应该 不 调用该方法,而只是将方法作为默认方法传递,而不是 return 实例 return 仅 pk
,理想情况下,此方法应该只是一个函数:
class ScheduleChoice(models.Model):
"""
This model allows users to define crontab schedules.
"""
label = models.CharField(max_length=256, verbose_name="Label", unique=True)
job_schedule = models.CharField(
max_length=256,
default="0 0 * * *", verbose_name="Crontab"
)
@classmethod
def get_choice_count(cls):
"""
Returns how many schedule choices have been defined.
"""
return len(cls.objects.all())
class Meta:
verbose_name = "schedule choice"
verbose_name_plural = "schedule choices"
def __str__(self):
return self.label
def get_default_schedule_choice():
choice, _created = ScheduleChoice.objects.get_or_create(
label="Every minute",
job_schedule="* * * * *"
)
# Why would programming error occur?
return choice.pk # Return the pk
class MyOtherModel(models.Model):
"""
Model using ScheduleChoices.
"""
job_schedule = models.ForeignKey(
"ScheduleChoice",
on_delete=models.SET_DEFAULT,
default=get_default_schedule_choice, # Don't call the function, only pass it
verbose_name="Schedule"
)
activated = models.BooleanField(default=False, verbose_name="activated")