【问题标题】:Django custom through table for ManyToMany relationship: save method not being called during model form save (or save_m2m)Django通过表自定义ManyToMany关系:模型表单保存(或save_m2m)期间未调用保存方法
【发布时间】:2020-05-12 13:15:24
【问题描述】:

这是设置...

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() 然后我在save_m2m() 调用上得到IntegrityError 异常。

为什么会这样? save() 在添加通过表条目时不会被调用吗?

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

更新:

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

【问题讨论】:

    标签: django python-3.x database


    【解决方案1】:

    好吧,永远无法确认这是否是 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 属性)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      • 2012-09-27
      • 2019-10-18
      • 1970-01-01
      • 2021-02-15
      • 1970-01-01
      • 2020-12-06
      相关资源
      最近更新 更多