【问题标题】:Django, handling m2m change signals over a model with multi ManyToManyFieldDjango,在具有多个 ManyToManyField 的模型上处理 m2m 更改信号
【发布时间】:2017-06-04 14:33:06
【问题描述】:

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

    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 上针对任何类型的更改发送一个请求。 我想知道是否有人可以帮助我:)

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

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

【问题讨论】:

  • 您能举个例子吗?您是如何解决您的问题的?

标签: django-models django-signals m2m


【解决方案1】:

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

【讨论】:

  • 感谢您的回复,不幸的是,这在我的情况下不起作用,因为当包含由 post_save 信号接收的 m2mfields 的模型实例与前一个具有相同的值时,直到 m2mfields 将在 post_save 之后保存!
【解决方案2】:

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

希望对您有所帮助!

【讨论】:

    猜你喜欢
    • 2019-10-19
    • 2014-12-18
    • 2015-06-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    相关资源
    最近更新 更多