Django,在具有多个ManyToManyField的模型上处理m2m更改信号

时间:2017-01-19 18:50:15

标签: django-models django-signals m2m

我有一个模型M包含三个不同的字段(a,b,c)到django中的三个不同模型。

    class M (models.Model):
           name = models.CharField()
           a = models.ManyToManyField(A)
           b = models.ManyToManyField(B)
           c = models.ManyToManyField(C)

现在,我想处理我的模型M上的任何更改,并相应地将HttpRequest发送到URL。 如您所知,在模型M的保存后信号中,a,b和c的属性值尚未设置,因为它们将在保存模型M完成时设置。(ManyToManyField的规则)

我为我的模型编写了一个处理程序来处理任何更改(创建新实例或更新字段/字段)

    @receiver(post_save, sender=M)
    @receiver(m2m_changed, sender=M.a.through)
    @receiver(m2m_changed, sender=M.b.through)
    @receiver(m2m_changed, sender=M.c.through)
    def M_changes_handler(sender, **kwargs):
          is_instance_set_compeletly(kwargs['instance']):
              #send_and_HttpRequest(url, data = instance)


    def is_instance_set_compeletly(kwargs['instance']):
          if M.a.all() is not None and M.b.all() is not None and 
              M.c.all()is not None
             flag = True
          else:
             flag = False
          return flag

现在考虑模型M上的更新请求(更改所有字段)将为所有字段a,b和c发送信号;因此,三个httpRequests将通过三个不同版本的实例发送给我的发件人!另一方面,当用户只更改一个字段,例如模型M的b时,此函数将只发送一个httpRequest。

我想动态处理这个问题,只需在我的模型M上按任何类型的CHANGE发送一个请求。 我想知道是否有人可以帮助我:)。

*请注意,上面的代码只是一个草稿,可能包含语法错误,因此请忽略它们;)

更新:我的问题解决了! 保存包含m2mfields的模型的过程很有意思! 首先,M的字段不是m2m字段类型,例如,在调用post_save之前已经设置了char字段,外键等。所以在post_save中他们的值会更新 虽然m2mfields不会被设置,直到模型的保存完成。然后调用m2mchange信号来设置m2mfields 获得模型更新版本的唯一方法是覆盖admin.py中的表单保存,因为在完成所有m2mfields设置后将调用“表单保存”

2 个答案:

答案 0 :(得分:0)

您可以保存以前的M实例,并且在post_save中使用新的M检查字段已根据您可以发送请求而更改。

答案 1 :(得分:0)

解决方案: 对于所有堆栈溢出用户和亲爱的Blake Gibbs 如果模型包含许多字段并且您想要访问已保存记录的所有数据,则无法访问这些m2m字段,因为它们将在完成保存模型的过程后保存(在我的示例中考虑M),然后将该Id分配给其他自创的m2m表将Id绑定到m2m字段(例如,在我的示例中为A)。所以在这种情况下,覆盖admin.py中模型的save方法不起作用。 我只是在Forms.py

中覆盖我的表单的保存功能

类MForm(forms.ModelForm):

class Meta:
        model = M          
        exclude = []
def save(self, commit=True):
    query = ""
    old_instance = super(MForm, self).save(commit=False)# if you need the old instance

#otherwise return super(MForm,self).save(commit = True)

    instance = super(MForm,self).save(commit=True)

在这种情况下,“实例”确实完全保存,您可以使用“.all()”访问m2m字段

希望它有所帮助!