Python Django原子事务句柄唯一约束

Python Django原子事务句柄唯一约束,python,python-3.x,django,Python,Python 3.x,Django,我有一个模型 class Order(models.Model): order_id = models.CharField(max_length=30, default='', unique = True) amount = models.FloatField() 我有一个循环,它将对象从json保存到我的数据库,并验证唯一字段order\u id for json_obj in json_data: order = Order(symbol=json_obj['order_id

我有一个模型

class Order(models.Model):
  order_id = models.CharField(max_length=30, default='', unique = True)
  amount = models.FloatField()
我有一个循环,它将对象从json保存到我的数据库,并验证唯一字段
order\u id

for json_obj in json_data:
   order = Order(symbol=json_obj['order_id'], amount= json_obj['amnount'])
   try:
     order.save()
   except IntegrityError as exception:
     if 'UNIQUE constraint failed' in exception.args[0]:
        print('duplicate order id => skip this')
        continue
一切正常,但当我在函数中添加@transaction.atomic decorator时,一切都会中断。 我得到一个错误:

 "An error occurred in the current transaction. You can't "
    django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
建议如何处理此类案件

UPD:我使用事务原子装饰器来加速我的代码,因为 有大量的订单要保存,这是一个相当昂贵的操作 在后台运行

UPD2:我尝试使用
get\u或\u create方法
,但没有得到任何实际的结果 使用它可以提高性能,因此无法使用它


首先,
transaction.atomic
decorator将数据库提交延迟到修饰函数的末尾。因此,您的异常处理现在将不起作用,因为异常被抛出到try-except块之外。 还建议您不要捕获原子块内的异常

也许这也会给您带来
事务管理错误的麻烦。如果原子块内发生异常,则不允许执行任何数据库查询

您应该将try-except移到您的功能之外,并检查是否解决了您的问题。

引用:

捕捉数据库错误的正确方法是围绕原子块

下面是对您的代码的修改:

从django.db导入IntegrityError,事务
对于json_数据中的json_obj:
订单=订单(symbol=json\u obj['order\u id'],amount=json\u obj['amnount']))
尝试:
使用transaction.atomic():
order.save()
除完整性错误作为例外:
如果异常中的“唯一约束失败”。参数[0]:
打印('重复订单id=>跳过此')
持续
您还可以使用
get\u或\u create
实现您想要的:

json_数据中的json_obj的
:
obj,created=Order.objects.get\u或\u create(
symbol=json_obj['order_id'],
默认值={'amount':json_obj['amnount']},
)
如果未创建:
打印('订单id已存在=>跳过此')
如果你想要一个快速的代码(根据你的评论),你可以使用

orders\u to\u create=[]
对于json_数据中的json_obj:
orders\u to\u create.append(Order(symbol=json\u obj['Order\u id'],amount=json\u obj['amnount']))
Order.objects.bulk\u create(orders\u to\u create,ignore\u conflicts=True)
请注意

在支持它的数据库(Oracle除外)上,将ignore_conflicts参数设置为True会告诉数据库忽略插入任何未通过约束(例如重复的唯一值)的行的失败

不使用
ignore\u conflicts
设置,您可以执行以下操作:

orders\u to\u create=[]
order_id=[json_obj['order_id']用于json_数据中的json_obj]
现有的\u顺序\u ID=order.objects.filter(symbol\u in=order\u ID).值\u列表('symbol',flat=True)
对于json_数据中的json_obj:
#此条件可防止对现有订单id的任何整数错误
如果json_obj['order_id']不在现有的_order_id中:
orders\u to\u create.append(Order(symbol=json\u obj['Order\u id'],amount=json\u obj['amnount']))
Order.objects.bulk\u create(orders\u to\u create)

据我所知,如果我将try移到我的函数之外,它将不会在发生错误时将任何内容保存到数据库中,但我想保存唯一的记录。您为什么要添加一个
事务原子
装饰器?在这种情况下,您希望将其添加到代码中有什么好处?@ArakkalAbu我有很多订单对象,所以当我使用transaction.atomic时,我的代码运行得非常快。我尝试了第一个和第二个选项,正如您所建议的,很遗憾,我的代码使用这种解决方案没有加快速度。@user2950593速度不是您的要求之一,但这是否解决了您在问题(代码中断)中提到的问题?@user2950593我添加了另一个代码块,这可能会加快您的代码速度。如果我编写ignore_conflicts=True,它是否会违反唯一约束要求,或者只是跳过这些命令?(稍后将尝试此操作)Ignore=True:启用此参数将禁用在每个模型实例上设置主键(如果数据库正常支持)。(C) -听起来很吓人