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

时间:2018-09-07 18:45:17

标签: python-3.x django-2.0

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

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

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

            if (!form2.IsHandleCreated)
            {          
             form2.CreateControl();
            }


            form2.Invoke((MethodInvoker) delegate
            {
             //Do Stuff Here.
            }

但是,我看不到应该在哪里添加旧版默认值。

PS:说实话,我根本不希望在迁移中使用默认的默认设置。我更希望将其设置在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), ), ] 中,以便阅读代码的人很清楚发生了什么。但是我认为它必须在迁移中,而我将在models.py中留下评论。

1 个答案:

答案 0 :(得分:1)

似乎没有任何方法可以在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。