【问题标题】:Django model form: reverse side of m2m not savingDjango模型形式:m2m的反面不保存
【发布时间】:2018-11-25 06:09:23
【问题描述】:

从 Django 1.8 (python 2.7) 升级到 Django 2.0 (python 3.6) 后,此表单和反向 m2m 小部件出现错误:

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

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

。 这是治疗模型的表格。它还允许编辑专业(反向 m2m)。升级前它运行良好。

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',
            ....)

我收到此错误:

TypeError at /customadmin/treatdetail/2/de/ 直接分配给 禁止多对多集合的反面。采用 specialties.set() 代替。

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

我当然试过了:

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

错误消失,但反向m2m关系没有保存。

有人可以帮忙吗?

【问题讨论】:

    标签: django django-forms django-orm


    【解决方案1】:

    你做错了。您必须将项目添加到 Django 2.0 中的 M2M 关系,例如 this:

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

    如果 self.cleaned_data['specialties']specialties 的列表 - 您必须遍历它们并以相同的方式逐一添加到您的 treatment.specialties

    【讨论】:

    • 啊,我明白了。谢谢。我用treatment.specialties.clear()treatment.specialties.add(*self.cleaned_data['specialties'])解决了
    • 如果您使用set() 而不是add(),那么您不必先调用clear()
    • @Alasdair 你能解释一下你的意思或提供解释的链接吗?在你的话之后,我真的在m2m docs 中找到了.set() 方法,但是它的描述只有1行并且不清楚。 (据我了解,您实际上可以添加一个列表而不是单个项目?您的意思是不同的吗?)
    • 上面的答案说使用treatment.specialties.add(self.cleaned_data['specialties'])。由于self.cleaned_data['specialties'] 是一个列表,您需要将其更改为treatment.specialties.add(*self.cleaned_data['specialties']) 。我建议您改用treatment.specialties.set(self.cleaned_data['specialties']),这样您就不必先调用clear()。在many-to-many 文档中有一个使用set() 的示例。
    猜你喜欢
    • 2014-01-30
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2012-12-24
    • 1970-01-01
    • 2010-10-22
    • 2015-07-25
    • 1970-01-01
    相关资源
    最近更新 更多