如何在Django模型中根据另一个模型中的字段设置新字段?

huangapple go评论46阅读模式
英文:

How to set a new field in django models based on another field in another model?

问题

I have a model like this:

class Foo(models.Model):
    ...
    status = models.PositiveSmallIntegerField(verbose_name=_('status'))
    ...

and another model like this:

class Bar(models.Model):
    foo = models.ForeignKey(to=Foo, on_delete=models.CASCADE)
    ...

I want to remove the status field from Foo and add it to Bar.
But this is a new field and must be filled with a value.
I want to fill it with the status value in bar_obj.foo which is supposed to be deleted.
How can I do this?

英文:

I have a model like this:

class Foo(models.Model):
    ...
    status = models.PositiveSmallIntegerField(verbose_name=_('status'))
    ...

and another model like this:

class Bar(models.Model):
    foo = models.ForeignKey(to=Foo, on_delete=models.CASCADE)
    ...

I want to remove the status field from Foo and add it to Bar.
But this is a new field and must be filled with a value.
I want to fill it with the status value in bar_obj.foo which is supposed to be deleted.
How can I do this?

答案1

得分: 2

你可以分两步来完成这个操作:

步骤1:添加字段和数据迁移

首先,在Bar模型中添加字段:

class Bar(models.Model):
    foo = models.ForeignKey(to=Foo, on_delete=models.CASCADE)
    status = models.PositiveSmallIntegerField(verbose_name=_('status'), default=0)

很重要的是给字段一个默认值,或者在这个阶段将其设为null=True,这样我们可以临时给字段赋值。

然后运行makemigrations命令,它会创建一个迁移。我们将修改这个迁移,添加一个数据迁移 [Django-doc]

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

def copy_values(apps, schema_editor):
    Bar = apps.get_model('<app_name>', 'Bar')
    Bar.objects.update(status=F('foo__status'))

class Migration(migrations.Migration):
    dependencies = [('app_name', '0123_prev_migration')]

    operations = [
        migrations.AddField(
            'Bar', 'status', models.PositiveSmallIntegerField(default=0)
        ),
        migrations.RunPython(copy_values),
    ]

建议您迁移此迁移并检查数据是否有效。

步骤2:从Foo模型中移除status字段

接下来,我们可以从Foo模型中删除status字段:

class Foo(models.Model):
    ...
    # status = models.PositiveSmallIntegerField(verbose_name=_('status'))

如果需要的话,我们也可以从Bar模型的status字段中删除default值。

然后再次创建一个迁移并执行迁移。

英文:

You can do this in two steps:

Step 1: add the field and a data migration

first add the field to the Bar model:

<pre><code>class Bar(models.Model):
foo = models.ForeignKey(to=Foo, on_delete=models.CASCADE)
<b>status</b> = models.PositiveSmallIntegerField(verbose_name=_('status'), <b>default=0</b>)</code></pre>

It's important to give the field a default value, or make it null=True in this stage, such that we can temporarily give the field values.

If we then run make migrations, it will make a migration. We will alter the migration, and add a data migration [Django-doc] to it:

<pre><code>from django.db import migrations, models
from django.db.models import F

def copy_values(apps, schema_editor):
# We can't import the Person model directly as it may be a newer
# version than this migration expects. We use the historical version.
Bar = apps.get_model('<em>app_name</em>', '<em>Bar</em>')
Bar.objects.update(<b>status=F('foo__status')</b>)

class Migration(migrations.Migration):
dependencies = [('<em>app_name</em>', '<em>0123_prev_migration</em>')]

operations = [
    migrations.AddField(
        &amp;quot;&lt;em&gt;Bar&lt;/em&gt;&amp;quot;, &amp;quot;status&amp;quot;, models.PositiveSmallIntegerField(default=0)
    ),
    migrations.RunPython(copy_values),
]&lt;/code&gt;&lt;/pre&gt;

I would suggest that you migrate this migration and check if the data is valid.

Step 2: remove the status field on Foo

Next we can remove the status field from the Foo model:

<pre><code>class Foo(models.Model):
&hellip;
# <s>status = models.PositiveSmallIntegerField(verbose_name=_('status'))</s></code></pre>

we can also remove the <code>default=&hellip;</code> value from the status field on Bar if necessary.

We make another migration and we can migrate.

huangapple
  • 本文由 发表于 2023年7月18日 14:43:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76710129.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定