Одно из решений по обновлению м2, наряду с обновлением одной из ваших моделей.
Django 1.11 and higher
Прежде всего, все запросы через админ-панель являются атомарными. Вы можете посмотреть на ModelAdmin:
@csrf_protect_m
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
with transaction.atomic(using=router.db_for_write(self.model)):
return self._changeform_view(request, object_id, form_url, extra_context)
@csrf_protect_m
def delete_view(self, request, object_id, extra_context=None):
with transaction.atomic(using=router.db_for_write(self.model)):
return self._delete_view(request, object_id, extra_context)
Поведение, которое вы можете наблюдать во время обновления, когда изменения, которые вы сделали с записями m2m, не были сохранены, даже после того, как вы сделали их в методе сохранения одной из ваших моделей или в сигнале, происходит только потому, что форма m2m переписывает все записи после обновления основного объекта.
Вот почему, шаг за шагом:
Основной объект обновлен.
Ваш код (в методе сохранения или в сигнале) внес изменения (вы можете посмотреть их, просто поставив точку останова в ModelAdmin):
def save_related(self, request, form, formsets, change):
breakpoint()
form.save_m2m()
for formset in formsets:
self.save_formset(request, form, formset, change=change)
- form.save_m2m () принимает все значения m2m, которые были размещены на странице (грубо говоря), и заменяет все записи m2m через связанный менеджер. Вот почему вы не видите свои изменения в конце транзакции.
Есть решение: внесите изменения с помощью m2m через
transaction.on_commit
. транзакция.on_commit внесет ваши изменения
после form.save_m2m (), когда транзакция совершена.
К сожалению, обратная сторона этого решения - ваши изменения с m2m будут выполнены в отдельной транзакции.