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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50015204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 19:22:01  来源:igfitidea点击:

Direct assignment to the forward side of a many-to-many set is prohibited. Use emails_for_help.set() instead

pythondjangodjango-ormm2m

提问by conf

I am new to Django and didn't find any reference regarding this issue. I am getting this error when i use many to many field in Django model (models.py). I guess the issue is assigning m2m field in view(views.py) from form(forms.py).

我是 Django 的新手,没有找到有关此问题的任何参考资料。当我在 Django 模型 ( models.py) 中使用多对多字段时出现此错误。我猜问题是views.py从 form( forms.py) 中在 view( ) 中分配 m2m 字段。

How to assign m2m field in view? (Django version 2.0, python - 3.5)

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

models.py

模型.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

视图.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

表格.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"]

回答by MD. Khairul Basar

You need to get the Userobject and then add it to emails_for_helpfield. You can't add an object to ManyToManyFieldwhen creating an instance. Have a look at the doc.

您需要获取User对象,然后将其添加到emails_for_help字段中。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')
        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("/")

EDIT

编辑

Another way of doing this is to use .set().

另一种方法是使用.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("/")

Or you can simply use .add()to add arbitrary number of objects.

或者您可以简单地使用.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("/")

回答by Animesh Kumar

I tried all the above solutions and it doesn't work on Django 3.0 . So, I did my own research and came up with the solution. The solution is gonna be pretty simple. My answer is in general. Let us say there exists a form-field specialFieldNamewhich is defined as a ManyToManyFieldin models.py.

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

Why did that error occur?

为什么会出现这个错误?

The options of this field which the user entered through the 'django form' are stored as a Queryset. In this scenario, we simply cannot assign this queryset to a ManyToManyFieldattribute during the creation of the object based on this queryset. This is the reason you are getting the above error.

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

So, we first create the object based on all the information we have got from the django-form, except the specialFieldNameand then we use add() method to add all the elements of this queryset to the object we just created.

因此,我们首先根据从 django-form 中获得的所有信息创建对象specialFieldName,然后我们使用 add() 方法将这个查询集的所有元素添加到我们刚刚创建的对象中。

So, we need to iterate over this queryset.

所以,我们需要迭代这个查询集。

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

Unfortunately, the loop doesn't iterate over all the members of the returnedQueryset (Read Why?). Thus, the above thing doesn't work. We gotta get a bit more advanced and use iterator() method instead.

不幸的是,循环不会遍历返回查询集的所有成员(阅读为什么?)。因此,上述事情不起作用。我们必须更高级一点,并改用 iterator() 方法。

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

Now it works fine.

现在它工作正常。

(P.S. This was my first answer on Stackoverflow. Gratitude for all my mentors ;-))

(PS 这是我在 Stackoverflow 上的第一个回答。感谢我所有的导师 ;-))