Вот решение, которое лучше, чем старые, которые действительно не работают.
При создании формы необходимо одновременно загрузить существующие связанные значения из базы данных и сохранить их обратно при сохранении формы. Я использую метод set()
для связанного имени (менеджера), который делает всю работу за вас: убирает существующие отношения, которые больше не выбираются, и добавляет новые, которые стали выбранными. Так что вам не нужно делать никаких циклов или проверок.
class AssignProjectForm(ModelForm):
def __init__(self, *args, **kwargs):
super(AssignProjectForm, self).__init__(*args, **kwargs)
# Here we fetch your currently related projects into the field,
# so that they will display in the form.
self.fields['projects'].initial = self.instance.projects.all(
).values_list('id', flat=True)
def save(self, *args, **kwargs):
instance = super(AssignProjectForm, self).save(*args, **kwargs)
# Here we save the modified project selection back into the database
instance.projects.set(self.cleaned_data['projects'])
return instance
Помимо простоты, использование метода set()
имеет еще одно преимущество, которое вступает в силу, если вы используете сигналы Django (например, post_save
и т. Д.) В отношении m2m: если вы добавляете и удаляете записи по одному за раз цикл, вы получите сигналы для каждого объекта. Но если вы сделаете это за одну операцию, используя set()
, вы получите только один сигнал со списком объектов. Если код в вашем обработчике сигналов выполняет значительную работу, это большое дело.