在自定义文件中工作但不在 Django 上的“自定义迁移”中工作的函数

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

我是 Django 初学者,刚刚开始学习迁移。在数据库表中,我试图删除具有特定字段值的行。当我创建使用 Django 设置的自定义文件时,该函数会正确删除该行。但是,当我在自定义迁移文件的另一个函数中使用该代码片段时,删除不会发生。

作为初学者,我可能错过了一些基本的东西。

所以我试图删除所有状态已取消的订单。 在单独文件中工作的函数是:

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_skeleton.settings")
django.setup()

from main_app.models import Order

def delete_test_fnc():
    all_orders = Order.objects.all()

    for i in range(len(all_orders) - 1, -1, -1):
        order = all_orders[i]
        if order.status == "Cancelled":
            order.delete()

delete_test_fnc()

删除不起作用的自定义迁移(其他两个修改可以正常工作)是:

from datetime import timedelta

from django.db import migrations

CURRENT_ORDERS = []

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

    all_orders = orders.objects.all()
    CURRENT_ORDERS = all_orders

    for i in range(len(all_orders) - 1, -1, -1):
        order = all_orders[i]
        if order.status == "Cancelled":
            order.delete()
        elif 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")
    orders.objects.all().delete()

    for order in CURRENT_ORDERS:
        new_order = orders.objects.create(
            product_name=order.get("product_name"),
            customer_name=order.get("customer_name"),
            order_date=order.get("order_date"),
            amount=order.get("amount"),
            product_price=order.get("product_price"),
            total_price=order.get("total_price"),
            warranty=order.get("warranty"),
            delivery=order.get("delivery")
        )
        new_order.save()


class Migration(migrations.Migration):

    dependencies = [
        ('main_app', '0021_order'),`your text`
    ]

    operations = [migrations.RunPython(
        modify_delivery_warranty, 
        reverse_code=revert_modify_delivery_warranty
    )
    ]
python django orm migration
1个回答
0
投票

代码的问题在于,如果状态为

Cancelled
,则调用
order.delete()
会将其从数据库中删除。但是Python对象本身仍然在内存中的变量
order
中。在所有if语句之后,您调用
order.save()
将对象保存回数据库。这意味着您的对象确实被删除,但又被保存了。

因此,解决此问题的方法是仅在需要时调用

order.save()

for i in range(len(all_orders) - 1, -1, -1):
    order = all_orders[i]
    if order.status == "Cancelled":
        order.delete()
    if order.status == "Pending":
        order.delivery = order.order_date + timedelta(days=3)
    elif order.status == "Completed":
        order.warranty = "24 months"

    if order.status != "Cancelled":
        order.save()

另一个重要的注意事项是,您实现的代码将不会恢复已删除的对象,因为一旦您运行

python manage.py migrate
并停止,所有内存中的对象都会在进程存在后被删除。这意味着当您尝试恢复迁移时,
CURRENT_ORDERS
将为空。有关此内容的更多信息:https://docs.djangoproject.com/en/4.2/topics/migrations/

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