You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django自定义迁移中删除Cancelled订单失效,普通文件可正常执行

Django迁移删除Cancelled订单失效的解决办法

问题根源

你的迁移代码里,删除Cancelled订单后又调用了order.save()——执行order.delete()已经把记录从数据库删掉了,但紧接着的save()会把这个实例重新插入回数据库,相当于白删了。而Pending/Completed状态的订单因为没执行删除,save()能正常保存修改,所以看起来只有删除操作失效。

快速修复

把order.save()移到非删除的分支里,避免删除后重新创建记录:

from datetime import timedelta
from django.db import migrations

def modify_delivery_warranty(apps, schema_editor):
    orders = apps.get_model("main_app", "Order")

    # 把QuerySet转为列表,防止遍历过程中数据变化导致的索引错位
    all_orders = list(orders.objects.all())

    # 倒序遍历(你原来的逻辑是对的,避免删除元素后影响后续遍历)
    for order in reversed(all_orders):
        if order.status == "Cancelled":
            order.delete()
        else:
            if order.status == "Pending":
                order.delivery = order.order_date + timedelta(days=3)
            elif order.status == "Completed":
                order.warranty = "24 months"
            # 只有非删除的订单才执行保存
            order.save()

# 修复反向迁移的问题:移除不可靠的全局变量,用正确的实例属性访问
def revert_modify_delivery_warranty(apps, schema_editor):
    orders = apps.get_model("main_app", "Order")
    
    # 恢复被修改的订单(这里的默认值请根据你的实际业务逻辑调整)
    for order in orders.objects.filter(status__in=["Pending", "Completed"]):
        if order.status == "Pending":
            order.delivery = None  # 替换成你原来的delivery默认值
        elif order.status == "Completed":
            order.warranty = "12 months"  # 替换成你原来的保修期默认值
        order.save()
    
    # 若需要恢复被删除的Cancelled订单,需在正向迁移时提前记录这些订单的数据
    # 比如在正向函数中将删除的订单数据存入辅助表,反向时读取重建

class Migration(migrations.Migration):
    dependencies = [
        ('main_app', '0021_order'),
    ]
    operations = [
        migrations.RunPython(
            modify_delivery_warranty, 
            reverse_code=revert_modify_delivery_warranty
        )
    ]

额外注意事项

  1. 别在迁移里用全局变量:Django迁移的正向和反向函数可能在不同上下文执行,全局变量无法持久化数据,会导致反向迁移失败。如果需要保存反向迁移所需的数据,建议在正向函数中将数据存入数据库的辅助表。
  2. 避免直接遍历QuerySet修改/删除:把QuerySet转为列表(list(orders.objects.all())),防止因为QuerySet的惰性求值特性,导致遍历过程中数据动态变化引发的异常。
  3. 反向迁移要谨慎:不要直接执行orders.objects.all().delete(),这会删除所有订单,包括迁移前就存在的无关记录,必须精准恢复被修改和删除的数据。

内容的提问来源于stack exchange,提问作者Polishko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 06:17:02