使用Django admin时ManyToMany字段未保存

g2ieeal7  于 2023-08-08  发布在  Go
关注(0)|答案(6)|浏览(127)

我遇到了一个奇怪的问题,我希望有人在这里可能能够摆脱一些光。
在运行super()之后,我将覆盖模型的保存()方法,以便向ManyToMany-field添加一些值。我的问题是,当我在Django admin中保存时,值似乎被添加到关系中,但随后又是空的。
但是如果我从manage.py shell做它,它工作没有问题。
我在里面放了两个print语句,不管我是通过Django admin还是通过shell运行它,它们都会产生完全相同的输出。

class Store(models.Model):
    holidays = models.ManyToManyField(StoreHoliday, blank=True)
    copy_holidays_from = models.ForeignKey('Store', blank=True, null=True)

    def save(self):
        print '====  BEFORE SAVE:', self.holidays.all()
        super(Store, self).save()
        self.copy_holidays()
        print '====  AFTER SAVE:', self.holidays.all()

    def copy_holidays(self):
        if self.pk and self.copy_holidays_from:
            self.holidays.clear()
            for h in self.copy_holidays_from.holidays.all():
                self.holidays.add( h )

字符串
下面是print语句的输出:

====  BEFORE SAVE: []
====  AFTER SAVE: [<StoreHoliday: 10 Mar 2010, Chuck Norris birthday (Closed)>]


有没有人有任何建议,可能是什么原因造成的?

**编辑:**所有在save()中对m2m关系的手动更改似乎在通过管理界面保存时会被Django丢弃。这与它处理表单的方式有关吗?

jq6vz3qz

jq6vz3qz1#

因此,上面的方法并不是实现它的正确方法。通过重写model_保存(),代码属于StoreAdmin。
我是这样解决的:

class StoreAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        if obj.copy_holidays_from:
            form.cleaned_data['holidays'] = obj.copy_holidays_from.holidays.all()

        super(StoreAdmin, self).save_model(request, obj, form, change)

字符串

2skhul33

2skhul332#

我今天可能遇到了同样的行为,是的,你假设这与django处理数据的方式有关是正确的。
django管理员将ManyToMany字段的更改与实际对象的更改分开。(请记住,m2m保存在不同的数据库表中)。
在我的例子中,如果我没有在管理站点的ManyToMany字段中选择任何内容,这将转换为ManyToMany关系上的clear()操作。你在保存()-方法中所做的一切都会立即被这个clear删除。与我在post_保存信号处理程序中所做的相同。
解决方案(对我来说)是将ManyToMany-field分隔成一个内联字段,这样在修改对象时它就不会自动保存为空。

nc1teljy

nc1teljy3#

在Django2,1,4中,我的解决方案是使用保存_related()

def save_related(self, request, form, formsets, change):
    super().save_related(request, form, formsets, change)
    form.instance.permissions.add(request.user)

字符串

xv8emn3q

xv8emn3q4#

对我来说,问题是管理员只保存最后选定的示例的许多领域(最后'假日'选定)。所以我必须重写保存_model方法,如下所示:

@admin.register(Store)
class StoreAdmin(admin.ModelAdmin):

    def save_model(self, request, obj, form, change):
        form.cleaned_data['holidays'] = StoreHoliday.objects.filter(pk__in=dict(request.POST).get('holidays'))
        super(StoreAdmin, self).save_model(request, obj, form, change)

字符串
我花了很多时间在上面,其他的解决方案都不起作用,所以我希望它能有所帮助。

crcmnpdw

crcmnpdw5#

更新m2m的解决方案之一,沿着更新您的模型之一。
第一个月
在更新过程中,当您对m2m记录所做的更改没有保存时,即使您在模型之一的save方法中或在信号中进行了更改,您可以观察到的行为也只是因为m2m表单在主对象更新后重写了所有记录。
这就是为什么,一步一步:
1.主对象将更新。
1.您的代码(在保存方法或信号中)进行了更改(您可以查看它们,只需在ModelAdmin中放置断点):

def save_related(self, request, form, formsets, change):
     breakpoint()
     form.save_m2m()
     for formset in formsets:
         self.save_formset(request, form, formset, change=change)

字符串

  1. form.save()获取放置在页面上的所有m2m值(粗略地说),并通过相关管理器替换所有m2m记录。这就是为什么在事务结束时看不到您的更改。
    有一个解决方案:通过transaction.on_commit使用m2m进行更改。transaction.on_commit将在提交事务时在form.save()之后进行更改。
    不幸的是,这种解决方案的缺点是-您对m2m的更改将在单独的事务中执行。
mctunoxg

mctunoxg6#

在我的情况下,它最终是因为我的数据库中的所有主键序列都不同步(..._id_seq表)。
在解决了这个问题(see this StackOverflow solution for that problem)之后,我的M2M模型再次开始保存。

相关问题