Django - 新字段:如何为现有对象设置默认的可调用函数

3

我有一个模型:

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

生产数据库中已经存在Model对象。 现在我向此模型添加price_total字段,该字段不能为null

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

我希望在迁移后,price_totalprice相等。

类似于:

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

有没有其他更好的方法呢?

目前我所知道的唯一方法如下:

  1. 使price_total可为空
  2. 执行makemigrations + migrate命令
  3. 例如通过django shellprice_total设置为等于price
  4. 使price_total不可为空
  5. 再次执行makemigration + migrate命令

但是这种方式有很多缺点,比如在生产环境中可能会忘记执行,步骤繁琐等等...

是否有更好的方法呢?

2个回答

9

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

  1. 使用null选项进行makemigrations操作
  2. 使用not null选项进行makemigrations操作
  3. 首先通过添加datamigration将第二个迁移文件中的更新和移动操作合并到第一个迁移文件中的make migration操作中
  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,
        ),
    ]

3

你正在正确的道路上。

只需确保第三步在 datamigration 中完成(绝对不要通过 Django shell 完成)。

这样,您就不会忘记在生产环境中运行它。

我非常确定您不能同时添加列并将其值设置为另一列的相同值。

要说服自己,您可以搜索像 https://dev59.com/12Yr5IYBdhLWcg3w--wI#13250005 这样的纯 SQL 实现。


1
我认为主要问题在于this_object部分。 - Willem Van Onsem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接