如何在 Django 中将现有的字符字段更改为外键

问题描述 投票:0回答:1

我有这个模型

class Order(models.Model):
 ...
 discount_code = models.CharField()

但在开发的某个阶段,我们决定从纯文本 discount_codes 转移到具有代码、百分比、开始和结束日期等的模型。这意味着我们必须更新到外键

class Order(models.Model):
 ...
 discount_code = models.ForeignKey(to=DiscountCode, on_delete=models.PROTECT, null=True, blank=True)

这期间产生了几百个订单,自然有些有优惠码。当谈到运行迁移时,我们无法做到,仅仅是因为 char 不是外键。

所以我决定更新迁移以处理从 char 到对象的移动,但它仍然失败。

这是迁移文件

# Generated by Django 3.2 on 2022-09-20 05:13

from django.db import migrations, models
import django.db.models.deletion
from datetime import date


def create_discount_objects(apps, schema_editor):
    Order = apps.get_model('orders', 'Order')
    DiscountCode = apps.get_model('orders', 'DiscountCode')

    # Get a list of unique discount codes from the existing orders
    discount_codes = Order.objects.exclude(discount_code=None).order_by('discount_code').values_list('discount_code', flat=True).distinct('discount_code')

    # Create new Discount objects for each discount code
    discount_objects = []
    for code in discount_codes:
        if code is not None:
            discount_objects.append(DiscountCode(code=code, percentage=10.0, start_date=date(2023,4,20), end_date=date(2023,4,20)))
    DiscountCode.objects.bulk_create(discount_objects)

    # Update the existing orders to link them to the corresponding Discount objects
    for order in Order.objects.all():
        if order.discount_code is not None:
            discount = DiscountCode.objects.get(code=order.discount_code)
            order.discount_code = discount
            order.save()

class Migration(migrations.Migration):

    dependencies = [
        ('orders', '0012_alter_requiredpart_part_quantity'),
    ]

    operations = [
        migrations.CreateModel(
            name='DiscountCode',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('code', models.CharField(max_length=255, unique=True)),
                ('percentage', models.FloatField()),
                ('status', models.CharField(choices=[('active', 'Active'), ('expired', 'Expired'), ('inactive', 'Inactive')], default='active', max_length=10)),
                ('start_date', models.DateField()),
                ('end_date', models.DateField()),
                ('notes', models.TextField(blank=True, null=True)),
            ],
        ),
        migrations.RunPython(create_discount_objects),
        migrations.AlterField(
            model_name='order',
            name='discount_code',
            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='orders.discountcode'),
        ),
    ]

这是我在运行时得到的错误

python manage.py migrate

TypeError: Tried to update field orders.Order.discount_code with a model instance, <DiscountCode: DiscountCode object (85)>. Use a value compatible with CharField.

任何帮助将不胜感激。

P.S 这没有帮助similar question

python-3.x django orm database-migration django-migrations
1个回答
1
投票

建议分步执行此操作(只涉及基础知识......没有复杂的手动迁移修改):

  1. 定义模型
    Discount
  2. 在模型
    Order
    中定义新的外键,临时名称如下:
discount_code_fk = models.ForeignKey(...)
  1. 做迁移

  2. 循环:像您一样从代码创建所有

    Discount
    实例并将
    Discount
    实例分配给
    discount_code_fk

  3. 从模型中删除

    discount_code
    Discount

  4. 迁移

  5. 在模型中将

    discount_code_fk
    重命名为
    discount_code
    Discount

  6. 迁移

© www.soinside.com 2019 - 2024. All rights reserved.