我是 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
)
]
代码的问题在于,如果状态为
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/