caliph
caliph

Reputation: 1439

Django model form: reverse side of m2m not saving

After upgrading from Django 1.8 (python 2.7) to Django 2.0 (python 3.6) I have an error with this form and reverse m2m widget:

models.py
class Treatment(Model):
  ...

class Specialty(Model):
  treatment = models.ManyToManyField(Treatment, related_name='specialties', blank=True)
  ...

. This is the Form for the treatment model. It allows to also edit the specialties (reverse m2m). It worked fine before the upgrade.

forms.py
class TreatDetail(forms.ModelForm):
    specialties = forms.ModelMultipleChoiceField(
        queryset=Specialty.objects.all().order_by('specialty_de'),
        required=False,
        widget=FilteredSelectMultiple('Specialties', False),

    )


    def save(self, commit=True):
        treatment = super(TreatDetail, self).save(commit=False)

        if commit:
            treatment.save()

        if treatment.pk:
            treatment.specialties = self.cleaned_data['specialties']
            self.save_m2m()

        return treatment

    def __init__(self, *args, **kwargs):
        super(TreatDetail, self).__init__(*args, **kwargs)
        if self.instance and self.instance.pk:
            self.fields['specialties'].initial = self.instance.specialties.all()

    class Meta:
        model = Treatment
        fields = (
            'top_treatment',
            'treatment_de',
            ....)

I get this Error:

TypeError at /customadmin/treatdetail/2/de/ Direct assignment to the reverse side of a many-to-many set is prohibited. Use specialties.set() instead.

treatment.specialties = self.cleaned_data['specialties']

Of course I tried:

treatment.specialties.set = self.cleaned_data['specialties']

The error disappears, but the reverse m2m relation is not saved.

Can anybody help here?

Upvotes: 1

Views: 565

Answers (1)

Chiefir
Chiefir

Reputation: 2671

You are doing that wrong. You have to add item to M2M relation in Django 2.0 like this:

treatment.specialties.add(self.cleaned_data['specialties'])

If self.cleaned_data['specialties'] is a list of specialties - you have to iterate over them and add one by one in the same way to your treatment.specialties.

Upvotes: 2

Related Questions