禁止直接赋值给多对多集合的前端。使用 emails_for_help.set() 代替
Direct assignment to the forward side of a many-to-many set is prohibited. Use emails_for_help.set() instead
我是 Django 的新手,没有找到关于这个问题的任何参考资料。当我在 Django 模型 (models.py
) 中使用多对多字段时出现此错误。我想问题是从表单(forms.py
)在视图(views.py
)中分配 m2m 字段。
如何在视图中分配m2m字段?
(Django version 2.0
, 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"]
您需要获取 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("/")
我尝试了以上所有解决方案,但它在 Django 3.0 上不起作用。因此,我进行了自己的研究并提出了解决方案。
解决方案将非常简单。我的回答一般。
假设存在一个表单字段 specialFieldName
,它在 models.py
中定义为 ManyToManyField
。
为什么会出现这个错误?
用户通过 'django form' 输入的该字段的选项存储为 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)
不幸的是,循环不会遍历 returnedQueryset 的所有成员(阅读 Why?)。因此,上面的事情是行不通的。我们得更高级一点,改用 iterator() 方法。
for member in returnedQueryset.iterator():
dummyObject.add(member)
现在可以正常使用了。
(P.S。这是我在 Whosebug 上的第一个答案。感谢我所有的导师 ;-))
从较旧的 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()]
试试这个代码,因为我在使用 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("/")
我是 Django 的新手,没有找到关于这个问题的任何参考资料。当我在 Django 模型 (models.py
) 中使用多对多字段时出现此错误。我想问题是从表单(forms.py
)在视图(views.py
)中分配 m2m 字段。
如何在视图中分配m2m字段?
(Django version 2.0
, 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"]
您需要获取 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("/")
我尝试了以上所有解决方案,但它在 Django 3.0 上不起作用。因此,我进行了自己的研究并提出了解决方案。
解决方案将非常简单。我的回答一般。
假设存在一个表单字段 specialFieldName
,它在 models.py
中定义为 ManyToManyField
。
为什么会出现这个错误?
用户通过 'django form' 输入的该字段的选项存储为 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)
不幸的是,循环不会遍历 returnedQueryset 的所有成员(阅读 Why?)。因此,上面的事情是行不通的。我们得更高级一点,改用 iterator() 方法。
for member in returnedQueryset.iterator():
dummyObject.add(member)
现在可以正常使用了。
(P.S。这是我在 Whosebug 上的第一个答案。感谢我所有的导师 ;-))
从较旧的 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()]
试试这个代码,因为我在使用 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("/")