Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
编辑时Django admin内联唯一约束冲突_Django_Django Admin - Fatal编程技术网

编辑时Django admin内联唯一约束冲突

编辑时Django admin内联唯一约束冲突,django,django-admin,Django,Django Admin,我有一个内嵌的表单。相关模型具有唯一的约束父项id,编号。我有一个有两个孩子的实体 parent_id | number | 1 | 1 | 1 | 2 | 我正试图在一次操作中将这些子项编辑到状态 parent_id | number | 1 | 2 | 1 | 3 | 保存时,第一个条目出现错误: 具有此父项id和编号的子项已存在 但是,如果我首先编辑第二个条目: parent_id

我有一个内嵌的表单。相关模型具有唯一的约束父项id,编号。我有一个有两个孩子的实体

parent_id | number |
        1 |      1 |
        1 |      2 |
我正试图在一次操作中将这些子项编辑到状态

parent_id | number |
        1 |      2 |
        1 |      3 |
保存时,第一个条目出现错误: 具有此父项id和编号的子项已存在

但是,如果我首先编辑第二个条目:

parent_id | number |
        1 |      1 |
        1 |      3 |
然后是第一个

parent_id | number |
        1 |      2 |
        1 |      3 |
在两个单独的操作中,它可以正常工作

家长管理定义

class ParentAdmin(admin.ModelAdmin):
    form = BaseForm

    inlines = [LevelExerciseInline]
class ChildInline(admin.StackedInline):
    form = BaseForm

    model = Child
    extra = 3
子行定义

class ParentAdmin(admin.ModelAdmin):
    form = BaseForm

    inlines = [LevelExerciseInline]
class ChildInline(admin.StackedInline):
    form = BaseForm

    model = Child
    extra = 3

由于您使用的是Django管理内联线,以下情况将不会发生:

我正试图在一次操作中将这些子项编辑到状态

parent_id | number |
        1 |      2 |
        1 |      3 |
内联线是完整表单的一部分,它们将按其在表单中的外观顺序进行处理。因此,即使您在一次操作中更改了它们,也就是说,您在一次表单发布期间更改了它们,Django仍将逐个保存这些相关对象:

列表中的第一个内联将被保存,当数据库中仍然有编号为2的父\u id 2时,它将尝试保存编号为2的父\u id 1

具体来说,调用formset.save,代码如下

注意:这里,表单是实际HTML表单的一部分,它只是变量的名称,不要混淆它

def save(self, commit=True):
    """Saves model instances for every form, adding and changing instances
    as necessary, and returns the list of instances.
    """
    if not commit:
        self.saved_forms = []

        def save_m2m():
            for form in self.saved_forms:
                form.save_m2m()
        self.save_m2m = save_m2m
    return self.save_existing_objects(commit) + self.save_new_objects(commit)
如您所见,调用save_m2m后,每个内联都保存在一个循环中。数组在表单中按外观顺序排序

不过,这与Django管理员的关系不大,更多的是关于它在数据库级别是否可行的问题。唯一可以工作的可能是事务,但即使这样-例如postgresql也不允许它,除非约束设置为延迟:

Postgresql文档:

因此,要改变行为,您需要:

通过调用原始SQL Django将唯一约束更改为至少在事务期间延迟,但Django不支持此操作,请参阅 重写formset.save以使用transaction.atomic
这是父项id主键吗?你能粘贴你的代码吗?我正在尝试通过一个操作将这些子项编辑到状态-你是否将queryset.update与F结合使用?显然,现在,您的代码会发出后续语句,DB会正确地拒绝它。@NVS对于父表,是的。对于儿童桌,不。@Risadinha我不明白你在说什么。我相信更新操作是由django管理员生成的。我没有为此做任何特殊的代码,只是定义了模型、管理表单和内联。谢谢你的回答。但是,如果我理解正确,如果我以向后的顺序更改子记录,如was[parent_id,2,parent_id,1],变成[parent_id,3,parent_id,2],它将起作用。有趣的是,事实并非如此,所以我认为真正的问题是完全不同的。除非你在两者之间存钱。如果您以任何顺序更改数字,并且之后只保存一次,那么唯一重要的顺序就是内联线在页面表单中的显示顺序。@Risadina我让它们以正确的顺序显示。这是家长id,2,家长id,1,我做了家长id,3,家长id,2。如果您是正确的,那么第一个将被保存为parent_id,3,并且在保存parent_id,2时,没有其他记录具有parent_id,2,因此它应该可以正常工作。但事实并非如此。我还深入研究了代码,它在Django验证级别失败,甚至没有尝试保存对象。