禁止直接分配到多对多集合的前端。请改用emails_for_help.set()

时间:2018-04-25 06:15:19

标签: python django

我是Django的新手,没有找到任何有关此问题的参考资料。当我在django模型(models.py)中使用多对多字段时,我收到此错误。我想问题是从窗体(forms.py)中查看视图(views.py)中的m2m。 如何在视图中指定m2m字段 Django版本2.O. python 3.5

models.py

class User(AbstractUser):
 username=models.CharField(max_length=20)
 email = models.EmailField(_('email address'), unique=True)


class Setupuser(models.Model):
 organization=models.CharField(max_length=200,blank=False,null=True)
 emails_for_help = models.ManyToManyField(User)

views.py

class Set_user(FormView):
 template_name="pkm_templates/set_up_user.html"
 form_class = Set_User_Form
 success_url = '/thanks/'
 def form_valid(self, form):
    org = form.cleaned_data.get('organization')
    emails = form.cleaned_data.get("emails_for_help")
    instance = Setupuser(organization=org,emails_for_help=emails)
    instance.save()
    return redirect("/")

forms.py

class Set_User_Form(ModelForm):
  emails_for_help = 
 forms.ModelMultipleChoiceField(queryset=User.objects.all(),
 widget=forms.CheckboxSelectMultiple)
 class Meta:
    model=Setupuser
    fields=["organization","emails_for_help"]

4 个答案:

答案 0 :(得分:12)

您需要获取User对象,然后将其添加到emails_for_help字段。创建实例时,无法将对象添加到ManyToManyField。看看doc

class Set_user(FormView):
    template_name="pkm_templates/set_up_user.html"
    form_class = Set_User_Form
    success_url = '/thanks/'

    def form_valid(self, form):
        org = form.cleaned_data.get('organization')
        emails = form.cleaned_data.get("share_email_with")

        users = User.objects.filter(email__in=emails)
        instance = Setupuser.objects.create(organization=org)

        for user in users:
            instance.emails_for_help.add(user)

        return redirect("/")

修改

另一种方法是使用.set()

class Set_user(FormView):
    template_name="pkm_templates/set_up_user.html"
    form_class = Set_User_Form
    success_url = '/thanks/'

    def form_valid(self, form):
        org = form.cleaned_data.get('organization')
        emails = form.cleaned_data.get("share_email_with")

        users = User.objects.filter(email__in=emails)
        instance = Setupuser.objects.create(organization=org)

        instance.emails_for_help.set(users)

        return redirect("/")

或者您只需使用.add()添加任意数量的对象。

class Set_user(FormView):
    template_name="pkm_templates/set_up_user.html"
    form_class = Set_User_Form
    success_url = '/thanks/'

    def form_valid(self, form):
        org = form.cleaned_data.get('organization')
        emails = form.cleaned_data.get("share_email_with")

        users = User.objects.filter(email__in=emails)
        instance = Setupuser.objects.create(organization=org)

        instance.emails_for_help.add(*users)

        return redirect("/")

答案 1 :(得分:6)

我尝试了上述所有解决方案,但在Django 3.0上不起作用。因此,我进行了自己的研究并提出了解决方案。 解决方案将非常简单。我的回答是一般的。 假设存在一个specialFieldName中定义为ManyToManyField的表单域models.py

为什么会发生该错误?

用户通过“ django表单”输入的该字段的选项存储为 Queryset 。在这种情况下,我们根本无法在基于该查询集创建对象的过程中将此查询集分配给ManyToManyField属性。这就是您收到上述错误的原因。

因此,我们首先根据django表单中除specialFieldName以外的所有信息创建对象,然后使用add()方法将此查询集的所有元素添加到对象中我们刚刚创建。

因此,我们需要遍历此查询集。

 returnedQueryset = form.cleaned_data.get('specialFieldName')
    dummyObject = ObjectModel.objects.create(..using all the info except specialFieldname..)
    for member in returnedQueryset:
        dummyObject.add(member)

不幸的是,循环并没有遍历返回的Queryset的所有成员(读Why?)。因此,上述操作无效。我们要更高级一些,而改为使用iterator()方法。

for member in returnedQueryset.iterator():
    dummyObject.add(member)

现在可以正常工作了。

(P.S。这是我对Stackoverflow的第一个答案。感谢所有导师;-))

答案 2 :(得分:0)

从较旧的 Django 版本升级到 Django 2.2 LTS 时,我遇到了同样的错误 Direct assignment to the forward side of a many-to-many set is prohibited. Use plan_options.set() instead

但是,当我使用 .set() 时,我得到了 SyntaxError: can't assign to function call。 对我来说,问题是通过添加 _set:

existing_plan.plan_options_set = [x.pk for x in old_plan.plan_options.all()]

答案 3 :(得分:0)

试试这个代码,因为我在使用 ManyToManyField 时遇到了同样的问题。

class Set_user(FormView):
 template_name="pkm_templates/set_up_user.html"
 form_class = Set_User_Form
 success_url = '/thanks/'

 def form_valid(self, form):
    org = form.cleaned_data.get('organization')
    instance = Setupuser(organization=org,emails_for_help=emails)
    instance.save()
    instance.email.add(request.user.email)
    instance.save()
    return redirect("/")