2 回答

TA貢獻1884條經驗 獲得超4個贊
引用Django 文檔:
捕獲數據庫錯誤的正確方法是圍繞一個原子塊
這是您的代碼的改編:
from django.db import IntegrityError, transaction
for json_obj in json_data:
? ? order = Order(symbol=json_obj['order_id'], amount=json_obj['amnount'])
? ? try:
? ? ? ? with transaction.atomic():
? ? ? ? ? ? order.save()
? ? except IntegrityError as exception:
? ? ? ? if 'UNIQUE constraint failed' in exception.args[0]:
? ? ? ? ? ? print('duplicate order id => skip this')
? ? ? ? ? ? continue
您還可以使用get_or_create來實現您想要的:
for json_obj in json_data:
? ? obj, created = Order.objects.get_or_create(
? ? ? ? symbol=json_obj['order_id'],
? ? ? ? defaults={'amount': json_obj['amnount'])},
? ? )
? ? if not created:
? ? ? ? print('order id already existing => skip this')
如果你想要一個快速的代碼(根據你的評論),你可以使用bulk_create。
orders_to_create = []
for json_obj in json_data:
? ? orders_to_create.append(Order(symbol=json_obj['order_id'], amount=json_obj['amnount']))
Order.objects.bulk_create(orders_to_create, ignore_conflicts=True)
請注意
在支持它的數據庫上(除 Oracle 之外的所有數據庫),將 ignore_conflicts 參數設置為 True 告訴數據庫忽略無法插入任何未通過約束(例如重復唯一值)的行
在不使用ignore_conflicts設置的情況下,您可以執行以下操作:
orders_to_create = []
order_ids = [json_obj['order_id'] for json_obj in json_data]
existing_order_ids = Order.objects.filter(symbol__in=order_ids).values_list('symbol', flat=True)
for json_obj in json_data:
? ? # this condition prevents any IntegrityError du to an existing order_id
? ? if json_obj['order_id'] not in existing_order_ids:
? ? ? ? orders_to_create.append(Order(symbol=json_obj['order_id'], amount=json_obj['amnount']))
Order.objects.bulk_create(orders_to_create)

TA貢獻1829條經驗 獲得超4個贊
首先,transaction.atomic
裝飾器將數據庫提交推遲到裝飾函數的末尾。因此,您的異常處理現在將不起作用,因為異常會在您的 try-except 塊之外拋出。文檔還建議您不要在原子塊內捕獲異常。
或許這也會給你帶來一個麻煩TransactionManagementError
。如果在原子塊內發生異常,則不允許執行任何數據庫查詢。
您應該將 try-except 移到您的函數之外并檢查是否可以解決您的問題。
添加回答
舉報