在django2中,如何分别为新对象和旧对象设置不同的默认值?

问题描述 投票:1回答:1

我想在现有模型中添加一个新字段。出于向后兼容性原因,我希望有两个默认值:

  • 通过迁移为遗留对象设置的一个
  • 一个用于模型的新实例

我可以看到在迁移中添加字段的代码非常简单:

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发表评论。

python-3.x django-2.0
1个回答
1
投票

似乎没有任何方法可以在models.py中指定旧版默认值,但是这可以通过迁移相当容易地完成。

例如,如果将新迁移secret_key添加到模型故障单,则会为此新字段创建两个迁移。一次迁移将该字段添加为null able字段,然后使用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。

© www.soinside.com 2019 - 2024. All rights reserved.