Django -- 新领域:如何为现有对象设置默认可调用对象

Django -- new field: How to set default callable for existing objects

我有一个模型:

class Model(models.Model):
    price = models.DecimalField(...)

生产数据库中已经有 Model 个对象。 现在我将 price_total 字段添加到此模型,该字段不能是 null.

class Model(models.Model):
    price = models.DecimalField(...)
    price_total = models.DecimalField(...)

我希望此 price_total 在迁移后立即等于 price

类似于:

price_total = models.DecimalField(default=this_object.price,...)

有办法做到吗?

我唯一知道的是:

  1. 使 price_total 可为空
  2. makemigrations + 迁移
  3. 设置 price_total 等于 price 例如通过 django shell
  4. 使 price_total 不可为空
  5. makemigration + 迁移

但是这种方式有很多缺点,你可能会在生产中忘记这样做,它有很多步骤等等...

有没有更好的方法?

您正在按计划正确执行。

只需确保第 3 步在 datamigration 中完成(当然不是通过 django shell)。

这样你就不会忘记 运行 它在生产中。

我很确定您不能既添加列又将值设置为与另一列相同。

为了说服自己,您可以搜索原版 SQL 实现,例如

您可以通过手动编辑迁移来完成,

  1. 使用 null 进行 makemigrations
  2. 不为 null 进行 makemigrations
  3. 编辑首先通过从第二个迁移文件添加具有更新和移动操作的数据迁移来进行迁移
  4. 删除第二个迁移文件,

例如:

from django.db import migrations, models
from django.db.models import F

def set_price_total(apps, schema_editor):
    # Change the myapp on your
    Model = apps.get_model('myapp', 'Model')
    Model.objects.update(price_total=F('price'))


class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='model',
            name='price_total',
            field=models.DecimalField(
                decimal_places=2, max_digits=10, null=True),
        ),

        migrations.RunPython(set_price_total),

        migrations.AlterField(
            model_name='model',
            name='price_total',
            field=models.DecimalField(
                decimal_places=2, default=1, max_digits=10),
            preserve_default=False,
        ),
    ]