2017-01-13 3 views
0

У меня возникла проблема с тем, как формы на основе Django сохраняют форму. Я использую form.ModelForm для одной из моих моделей, которая имеет некоторые отношения «многие ко многим».Форма модели Django сохраняет m2m после экземпляра

В методе сохранения модели, я проверить значение некоторых из этих отношений, чтобы изменить другие атрибуты:

class MyModel(models.Model): 
    def save(self, *args, **kwargs): 
    if self.m2m_relationship.exists(): 
     self.some_attribute = False 
    super(MyModel, self).save(*args, **kwargs) 

Даже если я заселена некоторые данные в отношениях m2m в моей форме, я self.m2m_relationship при сохранении модели и на удивление это был пустой QuerySet. В конце концов я обнаружил следующее:

Метод form.save() вызывается для сохранения формы, он относится к классу BaseModelForm. Затем этот метод возвращает save_instance, функцию в forms\models.py. Эта функция определяет локальную функцию save_m2m(), которая сохраняет отношения «многие ко многим» в форме.

Вот вещь, проверить порядок save_instance выбирает при сохранении и экземпляра и M2M:

instance.save() 
save_m2m() 

Очевидно, что вопрос здесь. Метод экземпляра save называется первым, поэтому self.m2m_relationship был пустым QuerySet. Этого еще не существует.

Что я могу сделать? Я не могу просто изменить порядок в функции save_instance, потому что это часть Django, и я могу сломать что-то еще.

ответ

2

Ответ Даниила дает причину такого поведения, вы не сможете его исправить.

Но есть m2m_changed сигнал, который посылается всякий раз, когда что-то меняется об отношениях m2m, и, возможно, вы можете использовать это:

from django.db.models import signals 

@signals.receiver(signals.m2m_changed, sender=MyModel.m2m_relationship.through) 
def handle_m2m_changed(sender, instance, action, **kwargs): 
    if action == 'post_add': 
     # Do your check here 

Но обратите внимание, что docs сказать, что экземпляр «может быть экземпляром отправителя , или класса ManyToManyField связан с ".

Я не знаю, как это работает, но вы можете попробовать, что вы получаете, а затем адаптируете код.

+0

Итак, что говорит документ, в основном, что сигнал будет срабатывать, если оба «MyModel» и экземпляр модели связаны, когда либо вносят изменения в существующую связь? – dabadaba

+0

Да, между ними есть невидимая таблица, это MyModel.m2m_relationship.through, если это изменяется, тогда сигнал отправляется независимо от того, как это произошло. Я не знаю, какой экземпляр отправлен, но вам нужно попробовать это. – RemcoGerlich

+0

Ну да, это действительно неважно, потому что это будет только «MyModel», который меняет его. И если это был другой, я думаю, что все-таки я бы изменил действие m2m, которое нужно применить в любом случае. – dabadaba

2

Но было бы невозможно сделать это иначе.

Отношение «многие ко многим» не является полем экземпляра, это запись в таблице ссылок. Невозможно сохранить эти отношения до того, как сам экземпляр существует, так как он не будет иметь идентификатор для входа в эту таблицу ссылок.

+0

поэтому что делать? Некоторые действия после сохранения, чтобы изменить то, что я хочу, на основе m2m? – dabadaba

Смежные вопросы