首页 > 解决方案 > Django通过表自定义ManyToMany关系:模型表单保存(或save_m2m)期间未调用保存方法

问题描述

这是设置...

class RequestUserBaseClass(Model):
    # There is middleware that sets "thread.request" with each request - that is functioning fine
    thread = threading.local()

    created_by = ForeignKey(User)

    ...
    def save(self, *args, **kwargs):
        self.created_by = RequestUserBaseClass.thread.request.user
    ...
    class Meta:
        abstract = True

class CustomThroughTable(RequestUserBaseClass):
    ...

class SimpleModelClass(RequestUserBaseClass):
    ...
    manyfield = ManyToManyField(OtherTable, through=CustomThroughTable)
    ...

class SimpleModelForm(ModelForm):
    class Meta:
        model = SimpleModelClass
        fields = [... 'manyfield' ... ]

在视图中...

if simple_form.is_valid():
    simple_form.save()

底线:我有这个基类,它通过与一些将用户置于线程局部变量中的自定义中间件一起工作来设置由字段创建。效果很好,到处使用。

然后我有一个ManyToManyField使用自定义直通表的模型。当表单被保存时,我收到一个关于created_by_id未设置的完整性错误,并且通过检查输出,这是将直通表中的条目添加到数据库中的时间。这是因为我只在ManyToManyField编辑后才收到错误。如果我这样做simple_form.save(commit=False)然后simple_form.save_m2m()单独打电话,那么我会在通话中遇到IntegrityError异常save_m2m()

为什么会这样呢?save()添加通过表条目或其他内容时不会被调用吗?

如果您认为出于某种原因需要它,请随时询问更多信息。我有空而且很难过......

更新:

我确认save()没有在自定义表格模型上调用它(只是添加了一个raise Exception('DEBUG')并且它从未被击中)。我想这只是意味着我需要手动保存我的 m2m 字段而不是使用该ModelForm#save()方法。在这一点上,我想我只是想知道是否有任何 Django 大师同意这种方法,或者认为它是我遇到的 Django 错误。

标签: djangopython-3.xdatabase

解决方案


好吧,永远无法确认这是否是 Django 错误,但我确实设法解决了(可能是真正的解决方法)这个问题。基本上只需要在视图中执行以下操作:

if simple_form.is_valid():
    form_data = deepcopy(simple_form.cleaned_data)

    # pop out m2m
    manyfield = form_data.pop("manyfield", [])

    # set non m2m fields
    for key, val in form_data.items():
        setattr(simple_model_instance, key, val)

    # Need to create through entries directly so that the throughclass#save()" gets called and sets created_by
    for manyentry in manyfield:
        CustomThroughTable.objects.get_or_create(...)

    simple_model_instance.save()

本质上:手动将表单数据应用于现有实例,然后通过表条目手动创建自定义,以便调用它们的保存方法(在我的具体示例中,因此调用抽象父级的保存方法并设置 created_by 属性)


推荐阅读