在 django2 中,如何分别为新对象和遗留对象设置不同的默认值?
In django2 how do I set a different default for new objects and legacy objects respectively?
我想向现有模型添加新字段。出于向后兼容的原因,我想要两个默认值:
- 一个是通过迁移为遗留对象设置的
- 一个用于模型的新实例
我可以看到在迁移中添加字段的代码非常简单:
operations = [
migrations.AddField(
model_name='queue',
name='permission_name',
field=models.CharField(help_text='Name used in the django.contrib.auth permission system', max_length=50, null=True, verbose_name='Django auth permission name', blank=True),
),
]
但是,我看不到应该在何处添加旧版默认值。
PS:说实话,我根本不想要迁移中的遗留默认值。我更希望将它设置在 models.py
中,这样阅读代码的人就可以清楚地知道发生了什么。但我认为它必须在迁移中,我会在 models.py
中发表评论。
似乎没有任何方法可以在 models.py
中指定遗留默认值,但是这可以通过迁移相当容易地完成。
例如,如果您向模型票证添加新迁移 secret_key
,您将为这个新字段创建两个迁移。一次迁移将该字段添加为可空字段,随后使用 RunPython
设置旧版默认值。
from django.db import migrations, models
import helpdesk.models
def clear_secret_keys(apps, schema_editor): # set the legacy default
Ticket = apps.get_model("helpdesk", "Ticket")
db_alias = schema_editor.connection.alias
for ticket in Ticket.objects.using(db_alias).all():
ticket.secret_key='<legacy-default>'
ticket.save()
class Migration(migrations.Migration):
dependencies = [
('helpdesk', '0017_default_owner_on_delete_null'),
]
operations = [
migrations.AddField(
model_name='ticket',
name='secret_key',
field=models.CharField(default='<default-for-new-objects>', max_length=36, null=True, verbose_name='Secret key needed for viewing/editing ticket by non-logged in users'),
),
migrations.RunPython(clear_secret_keys),
]
如果您不希望您的字段可以为空,则需要创建第二个迁移,将字段更改为不可为空:
from django.db import migrations, models
import helpdesk.models
class Migration(migrations.Migration):
dependencies = [
('helpdesk', '0018_ticket_secret_key'),
]
operations = [
migrations.AlterField(
model_name='ticket',
name='secret_key',
field=models.CharField(default='<default-for-new-objects>', max_length=36, verbose_name='Secret key needed for viewing/editing ticket by non-logged in users'),
),
]
写出这个答案时我想到还有另一种方法可以做到这一点,也有两个迁移,那就是首先设置遗留默认值,然后为新对象设置默认值:
from django.db import migrations, models
import helpdesk.models
class Migration(migrations.Migration):
dependencies = [
('helpdesk', '0017_default_owner_on_delete_null'),
]
operations = [
migrations.AddField(
model_name='ticket',
name='secret_key',
field=models.CharField(default='<legacy-default>', max_length=36, null=True, verbose_name='Secret key needed for viewing/editing ticket by non-logged in users'),
),
]
如果您不希望您的字段可以为空,则需要创建第二个迁移,将字段更改为不可为空:
from django.db import migrations, models
import helpdesk.models
class Migration(migrations.Migration):
dependencies = [
('helpdesk', '0018_ticket_secret_key'),
]
operations = [
migrations.AlterField(
model_name='ticket',
name='secret_key',
field=models.CharField(default=helpdesk.models.mk_secret, max_length=36, verbose_name='Secret key needed for viewing/editing ticket by non-logged in users'),
),
]
这两种方法都应该适用于动态默认值。例如,在这种情况下,新对象的默认值是一个名为 helpdesk.models.mk_secret
的方法,它为所有新创建的对象生成一个唯一的 uuid。
我想向现有模型添加新字段。出于向后兼容的原因,我想要两个默认值:
- 一个是通过迁移为遗留对象设置的
- 一个用于模型的新实例
我可以看到在迁移中添加字段的代码非常简单:
operations = [
migrations.AddField(
model_name='queue',
name='permission_name',
field=models.CharField(help_text='Name used in the django.contrib.auth permission system', max_length=50, null=True, verbose_name='Django auth permission name', blank=True),
),
]
但是,我看不到应该在何处添加旧版默认值。
PS:说实话,我根本不想要迁移中的遗留默认值。我更希望将它设置在 models.py
中,这样阅读代码的人就可以清楚地知道发生了什么。但我认为它必须在迁移中,我会在 models.py
中发表评论。
似乎没有任何方法可以在 models.py
中指定遗留默认值,但是这可以通过迁移相当容易地完成。
例如,如果您向模型票证添加新迁移 secret_key
,您将为这个新字段创建两个迁移。一次迁移将该字段添加为可空字段,随后使用 RunPython
设置旧版默认值。
from django.db import migrations, models
import helpdesk.models
def clear_secret_keys(apps, schema_editor): # set the legacy default
Ticket = apps.get_model("helpdesk", "Ticket")
db_alias = schema_editor.connection.alias
for ticket in Ticket.objects.using(db_alias).all():
ticket.secret_key='<legacy-default>'
ticket.save()
class Migration(migrations.Migration):
dependencies = [
('helpdesk', '0017_default_owner_on_delete_null'),
]
operations = [
migrations.AddField(
model_name='ticket',
name='secret_key',
field=models.CharField(default='<default-for-new-objects>', max_length=36, null=True, verbose_name='Secret key needed for viewing/editing ticket by non-logged in users'),
),
migrations.RunPython(clear_secret_keys),
]
如果您不希望您的字段可以为空,则需要创建第二个迁移,将字段更改为不可为空:
from django.db import migrations, models
import helpdesk.models
class Migration(migrations.Migration):
dependencies = [
('helpdesk', '0018_ticket_secret_key'),
]
operations = [
migrations.AlterField(
model_name='ticket',
name='secret_key',
field=models.CharField(default='<default-for-new-objects>', max_length=36, verbose_name='Secret key needed for viewing/editing ticket by non-logged in users'),
),
]
写出这个答案时我想到还有另一种方法可以做到这一点,也有两个迁移,那就是首先设置遗留默认值,然后为新对象设置默认值:
from django.db import migrations, models
import helpdesk.models
class Migration(migrations.Migration):
dependencies = [
('helpdesk', '0017_default_owner_on_delete_null'),
]
operations = [
migrations.AddField(
model_name='ticket',
name='secret_key',
field=models.CharField(default='<legacy-default>', max_length=36, null=True, verbose_name='Secret key needed for viewing/editing ticket by non-logged in users'),
),
]
如果您不希望您的字段可以为空,则需要创建第二个迁移,将字段更改为不可为空:
from django.db import migrations, models
import helpdesk.models
class Migration(migrations.Migration):
dependencies = [
('helpdesk', '0018_ticket_secret_key'),
]
operations = [
migrations.AlterField(
model_name='ticket',
name='secret_key',
field=models.CharField(default=helpdesk.models.mk_secret, max_length=36, verbose_name='Secret key needed for viewing/editing ticket by non-logged in users'),
),
]
这两种方法都应该适用于动态默认值。例如,在这种情况下,新对象的默认值是一个名为 helpdesk.models.mk_secret
的方法,它为所有新创建的对象生成一个唯一的 uuid。