2017-01-19 16 views
1

У меня есть модель M содержит три многотонных поля (a, b, c) для трех разных моделей в django.dajngo, обработка сигналов m2m по модели с несколькими ManyToManyField

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)

I написать один обработчик для моей модели для обработки каких-либо изменений (либо создать новый экземпляр или обновить поле/поля)

@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 отправят моему отправителю три версии экземпляра! с другой стороны, когда пользователь просто изменяет поле, например b модели M, эта функция отправит только один httpRequest.

Я хочу, чтобы справиться с этой проблемой динамически и просто отправить один запрос за любой тип изменений на моей модели М. мне было интересно, если кто-то может помочь мне :)

* Обратите внимание, что приведенный выше код только проект и может содержать синтаксическую ошибку, поэтому игнорируйте их;)

Обновление: моя проблема решена! Процесс сохранения модели, содержащей m2mfields, интересен! Прежде всего поля M, которые не являются полями m2m, например. это поле char, внешний ключ или т. д. были установлены перед вызовом post_save. Поэтому в post_save обновляются их значения Хотя m2mfields не будут установлены до тех пор, пока сохранение модели не будет закончено. Затем m2mchange сигналы, вызываемые для установки m2mfields . Единственный способ иметь обновленную версию вашей модели - это переопределить форму save в admin.py, потому что будет вызываться «сохранение формы» после завершения всех полей m2m.

+0

Можете ли вы добавить пример, как вы решили проблему? –

ответ

0

Вы можете удерживайте ранее экземпляр M и в post_save с новым полем проверки M изменились в соответствии с тем, что вы можете отправить запрос.

+0

Спасибо за ваш ответ, к сожалению, это не работает в моем случае, потому что, когда экземпляр модели, содержащий m2mfields, полученный по сигналу post_save, имеет такое же значение с предыдущим, пока m2mfields не будут сохранены после post_save! – Atefeh

0

Решение: Для всех пользователей стеки переполнения и Дорогой Blake Гиббса Если модель содержит manytomany поля, и вы хотите, чтобы получить доступ ко всем данным о сохраненной записи, вы не можете получить доступ к этим m2m полям, потому что они будут экономить после окончания процесс сохранения модели (рассмотрим M в моем примере), затем назначьте этот идентификатор другой созданной для создания таблицы 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 супер (MForm, самость) .save (совершить = True)

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

в этом случае «экземпляр» действительно сохранен полностью, и вы можете получить доступ к m2m полей с помощью «.all()»

надеюсь, что это помогло!