尝试使用save_formset将同一对象保存两次时的完整性错误

时间:2017-03-29 20:48:16

标签: django django-admin

我没有想法,我需要一些关于我在尝试保存同一个对象时遇到的问题的帮助。让我解释一下。

我有一个型号,我们称之为披萨 Topping ,其中包含 Pizza 的外键:

我已经实施了管理视图 PizzaAdmin ,我添加了一个表格内联 Topping

所以从PizzaAdmin,我可以添加几个浇头。

我已经覆盖 save_formset 方法,我调用帮助程序来执行第三方API调用。 从API响应中,我需要将一些数据保存到我的浇头。

def save_formset(self, request, form, formset, change):
    super(PizzaAdmin, self).save_formset(request, form, formset, change)

    helper = ApiHelper(instance=form.instance)
    helper.sync()

此帮助程序调用API,解析响应并为Pizza的每个配件关联ID。

class ApiHelper(...):
    def sync(self):
        # parse response

        for topping in self.instance.toppings.all():
            if ....:
                topping.some_id = ...
                topping.save()

当我到达topping.save()时,我收到了此错误:IntegrityError

我不想创建新的 Topping ,而是更新其属性some_id

经过进一步的调查,我意识到save_formsetsave_related调用,changeform_view调用@transaction.atomic作为装饰者class PizzaAdmin(admin.ModelAdmin) def save_formset(self, request, form, formset, change): super(PizzaAdmin, self).save_formset(request, form, formset, change) transaction.on_commit(lambda: sync_toppings(instance=form.instance)) def sync_toppings(instance): helper = ApiHelper(instance=form.instance) helper.sync()

有没有办法在原子事务中强制提交?

请指教。非常感谢。

***更新时间:2017-03-30 ***

我发现transaction.on_commit()允许我在提交后执行操作:

toppings_qs = Topping.objects.filter(pizza=self.instance)

sync()方法中,我使用此逻辑替换了我的查询集:

SELECT  A.Name AS "Avatar Name", 
        COUNT(H.WEAPON_ID) AS "Active Weapons Held |", 
        SUM(W.COST) AS "Total Weapons Cost"
FROM    Avatar      A
JOIN    Weapon_Held H   ON  A.Avatar_ID=H.AVATAR_ID
JOIN    Weapon      W   ON  H.WEAPON_ID=W.WEAPON_ID 
Group by A.Name;

当我尝试通过查询集更新顶部时,我仍然有 IntegrityError

我不明白为什么。请帮忙。

1 个答案:

答案 0 :(得分:0)

我发现了我的错误! 这就是我所做的:

def save(self, **kwargs):
    self.is_negative = True
    super(Topping, self).save(self, **kwargs)

注意保存super()时的 self :(

我的修复:

def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
    self.is_negative = True
    super(Topping, self).save(force_insert, force_update, using, update_fields)