【问题标题】:django.db.transaction.TransactionManagementError: cannot perform saving of other object in model within transactiondjango.db.transaction.TransactionManagementError:无法在事务中保存模型中的其他对象
【发布时间】:2021-12-19 04:04:59
【问题描述】:

似乎找不到太多关于此的信息。这不会发生在 django 测试中。我正在使用DATABASES = { ATOMIC_REQUESTS: True }。在视图调用的方法(在我创建的 mixin 中)中,我正在尝试执行以下操作:

def process_valid(self, view):
    old_id = view.object.id
    view.object.id = None       #  need a new instance in db
    view.object.save()
    old_fac = Entfac.objects.get(id=old_id)
    new_fac = view.object
    old_dets = Detfac.objects.filter(fk_ent__id__exact = old_fac.id)

    new_formset = view.DetFormsetClass(view.request.POST, instance=view.object, save_as_new=True)
    if new_formset.is_valid():
        new_dets = new_formset.save()

    
    new_fac.fk_cancel = old_fac    # need a fk reference to initial fac in new one
    old_fac.fk_cancel = new_fac    # need a fk reference to new in old fac

    # any save() action after this crashes with TransactionManagementError
    new_fac.save()

我不明白这个错误。我已经在 db 中创建并保存了一个新对象(当我将 object.id 设置为 None 并保存它时)。为什么创建其他对象会造成进一步保存的问题?

我尝试不使用 Formset 实例化 new_dets 对象,而是明确定义它们:

new_det = Detfac(...)
new_det.save()

但话又说回来,此后任何进一步的保存都会引发错误。

更多细节:

基本上,我有一个Entfac 模型和一个Detfac 模型,它有一个指向Entfac 的外键。我需要为新的Entfac 实例化一个新的Enfac(在数据库中不同),以及相应的新Detfac。然后我需要更改新旧对象的某些字段中的一些值,并将所有这些值保存到 db。

【问题讨论】:

    标签: django django-orm


    【解决方案1】:

    啊。上面的代码很好。

    但事实证明,信号可能很糟糕。我忘记了在保存Detfac, 时,有一个信号会转到另一个类,并且根据情况,将记录添加到另一个表(类似于历史表)。

    因为那个信号只是一个单一的操作。类似的东西:

    @receiver(post_save, sender=Detfac)
    def quantity_adjust_detfac(sender, **kwargs):
            try:
                detfac_qty = kwargs["instance"].qte
                product = kwargs["instance"].fk_produit
                if kwargs["created"]:
                    initial = {# bunch of values}
                    adjustment = HistoQuantity(**initial)
                    adjustment.save()
                else:
            except TypeError as ex:
                logger.error(f"....")
            except AttributeError as ex:
                logger.error(f"....")
    

    就其本身而言,没有将 THIS 标记为原子这一事实没有问题。但如果其中一个异常抛出,那么我得到事务管理错误。我仍然不是 100% 确定为什么,django 文档确实提到,当用原子(或任何代码块)包装整个视图时,然后在该块中尝试/排除会产生意想不到的结果,因为 DJango 确实依赖在异常情况下决定是否将事务作为一个整体提交。我测试的数据实际上引发了异常(创建 HistoQuantity 对象时出现类型错误)。

    但是,使用 transaction.atomic 管理器包装 try/exception 是可行的。猜测这...删除/处理了抛出,因此外部原子可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-01
      • 2010-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多