如何在 Django 迁移时设置/提供默认值?

JPG*_*JPG 5 django django-models django-migrations

场景
我有一个模型,Customer

class Customer(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
    company = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)


现在我用如下关系更新了company属性ForeignKey

class Company(models.Model):
    name = models.CharField(max_length=100)
    location = models.CharField(max_length=100)


class Customer(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
    company = models.ForeignKey(Company)
Run Code Online (Sandbox Code Playgroud)



我需要的是,当新的迁移应用于数据库时,相应的Company实例必须自动生成并映射到实例的company属性Customer

那可能吗?我怎样才能做到这一点?

Ant*_*ard 10

让我们从您的原始模型开始,一步一步来。

class Customer(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
    company = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)

首先,您必须保留原始字段并创建一个新字段,以便之后能够恢复旧数据。

class Customer(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
    company = models.CharField(max_length=100)
    _company = models.ForeignKey(Company)
Run Code Online (Sandbox Code Playgroud)

现在您可以使用manage.py makemigrations. 然后您必须创建数据迁移。使用manage.py makemigrations yourapp --empty并更新生成的文件创建迁移:

from django.db import migrations

def export_customer_company(apps, schema_editor):
    Customer = apps.get_model('yourapp', 'Customer')
    Company = apps.get_model('yourapp', 'Company')
    for customer in Customer.objects.all():
        customer._company = Company.objects.get_or_create(name=customer.company)[0]
        customer.save()

def revert_export_customer_company(apps, schema_editor):
    Customer = apps.get_model('yourapp', 'Customer')
    Company = apps.get_model('yourapp', 'Company')
    for customer in Customer.objects.filter(_company__isnull=False):
        customer.company = customer._company.name
        customer.save()

class Migration(migrations.Migration):

    dependencies = [
        ('yourapp', 'xxxx_previous_migration'),  # Note this is auto-generated by django
    ]

    operations = [
        migrations.RunPython(export_customer_company, revert_export_customer_company),
    ]
Run Code Online (Sandbox Code Playgroud)

上述迁移将填充您的Company模型,并Customer._company根据现场Customer.company

现在您可以删除旧的Customer.company并重命名Customer._company.

class Customer(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
    company = models.ForeignKey(Company)
Run Code Online (Sandbox Code Playgroud)

最终manage.py makemigrationsmanage.py migrate