代码之家  ›  专栏  ›  技术社区  ›  conf

禁止直接分配到多对多集合的前端。使用emails\u获取帮助。改为set()

  •  77
  • conf  · 技术社区  · 6 年前

    我是Django的新手,没有找到关于这个问题的任何参考资料。当我在Django模型中使用多对多字段时,出现了这个错误( models.py ).我想问题是分配视图中的m2m字段( views.py )来自表单( forms.py )。

    如何分配视图中的m2m字段? ( Django version 2.0 ,则, python - 3.5 )

    型号。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)
    

    视图。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("/")
    

    表格。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 回复  |  直到 3 年前
        1
  •  85
  •   Sabito stands with Ukraine ismail PANDA    3 年前

    你需要得到 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("/")
    
        2
  •  13
  •   Animesh Kumar    4 年前

    我尝试了以上所有的解决方案,但它在Django 3.0上不起作用。所以,我做了自己的研究,并提出了解决方案。 解决方案将非常简单。我的回答是一般性的。 假设存在一个表单字段 specialFieldName 定义为 ManyToManyField 在里面 models.py

    为什么会发生这种错误?

    用户通过“django表单”输入的此字段的选项存储为 查询集 。在这种情况下,我们无法将此查询集分配给 曼尼托曼尼菲尔德 基于此查询集创建对象期间的属性。这就是您出现上述错误的原因。

    因此,我们首先根据从django表单获得的所有信息创建对象,除了 特殊字段名称 然后我们使用add()方法将这个queryset的所有元素添加到我们刚刚创建的对象中。

    因此,我们需要迭代这个查询集。

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

    不幸的是,循环没有迭代returnedQueryset(读取 Why? ).因此,上述方法不起作用。我们需要更高级一点,改用迭代器()方法。

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

    现在它工作得很好。

    (附:这是我对Stackoverflow的第一个回答。感谢我所有的导师;-))

        3
  •  0
  •   SaeX    3 年前

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

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

    existing_plan.plan_options_set = [x.pk for x in old_plan.plan_options.all()]
    
        4
  •  0
  •   Rakesh Gombi    3 年前

    尝试此代码,因为我在使用 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("/")