禁止直接赋值给多对多集合的前向侧。请使用 emails_for_help.set() 代替。

2025-04-16 08:57:00
admin
原创
14
摘要:问题描述:我是 Django 新手,没有找到任何关于此问题的参考资料。我在 Django 模型 () 中使用多对多字段时出现此错误models.py。我猜问题出在views.pyform( forms.py) 中的 view() 中分配了 m2m 字段。如何在视图中分配 m2m 字段?(Django vers...

问题描述:

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

如何在视图中分配 m2m 字段?(Django version 2.0python - 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"]

解决方案 1:

您需要获取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("/")

另一种方法是使用.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:

我尝试了上述所有解决方案,但在 Django 3.0 上都不起作用。因此,我做了一些研究,最终找到了解决方案。这个解决方案其实很简单。我的答案很简单。假设存在一个表单字段specialFieldName,它被定义为ManyToManyFieldin models.py

为什么会出现这个错误?

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

因此,我们首先根据从 django-form 获得的所有信息创建对象,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 的所有成员(阅读为什么?)。因此,上面的方法不起作用。我们需要更高级一点,改用 iterator() 方法。

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

现在一切正常。

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

解决方案 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("/")

解决方案 4:

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()]

解决方案 5:

我可能没补充太多,但我在为一个完全没有表单的 REST API 进行单元测试时遇到了这个错误,所以我想提供一个示例,说明我是如何在这种情况下修复它的。我使用的是 Django 4.1.7 和 Django Rest Framework 3.14.0。

这是一个 Pokemon 卡片项目,因此有一个 PokemonType 模型(表示“火”、“水”、“草”等类型以及它们的抵抗力和弱点):

class PokemonType(models.Model):
    name = models.CharField(max_length=100, blank=False)
    strong_vs = models.ManyToManyField('self', symmetrical=False, related_name="strong_versus")
    weak_vs = models.ManyToManyField('self', symmetrical=False, related_name="weak_versus")
    resistant_to = models.ManyToManyField('self', symmetrical=False, related_name="resists")
    vulnerable_to = models.ManyToManyField('self', symmetrical=False, related_name="vulnerable")

我想编写一个简单的测试来验证是否可以创建 PokemonType,但是这个测试导致了Direct assignment to the forward side of a many-to-many set is prohibited错误:

class PokemonTypeModelTests(TestCase):
    def test_create_pokemontype(self):
        pokemon_type = PokemonType.objects.create(
            name = 'type 1',
            strong_vs = [],
            weak_vs = [2],
            resistant_to = [3, 4],
            vulnerable_to = [2, 5]
        )
        pokemon_type_from_db = PokemonType.objects.get(id=pokemon_type.id)
        self.assertEqual(pokemon_type_from_db.name, 'type 1')

人们可能会认为创建对象然后添加这样的关系可能会有所帮助:

pokemon_type = PokemonType.objects.create(name='type 1')
pokemon_type.resistant_to.set([3, 4])

但这会引发错误django.db.utils.IntegrityError: The row in table 'api_pokemontype_resistant_to' with primary key '1' has an invalid foreign key: api_pokemontype_resistant_to.to_pokemontype_id contains a value '3' that does not have a corresponding value in api_pokemontype.id.

发生这种情况是因为 ID 为 3 和 4 的 PokemonType 对象尚不存在(请记住,Django 为了测试目的创建了一个特殊的数据库)。多对多关系实际上是在数据库中作为单独的表实现的,Django 需要这些对象确实存在于数据库中,然后才能在它们之间添加关系。

这就是为什么在这种情况下的解决方案是首先创建所有对象,将它们添加到数据库,然后用于set()创建多对多关系:

def test_create_pokemontype(self):
    # this is the "main" object:
    pokemon_type = PokemonType.objects.create(name='type 1')
    
    # these are only created for the relationship fields:
    type2 = PokemonType.objects.create(name='type 2')
    type3 = PokemonType.objects.create(name='type 3')
    type4 = PokemonType.objects.create(name='type 4')
    type5 = PokemonType.objects.create(name='type 5')

    # now we can "set" these objects in each ManyToManyField:
    pokemon_type.strong_vs.set([])
    pokemon_type.weak_vs.set([type2])
    pokemon_type.resistant_to.set([type3, type4])
    pokemon_type.vulnerable_to.set([type2, type5])

    # and perform assertions with them:
    pokemon_type_from_db = PokemonType.objects.get(id=pokemon_type.id)
    self.assertEqual(pokemon_type_from_db.name, 'type 1')
    self.assertEqual(set(pokemon_type_from_db.strong_vs.all()), set())
    self.assertEqual(set(pokemon_type_from_db.weak_vs.all()), {type2})
    self.assertEqual(set(pokemon_type_from_db.resistant_to.all()), {type3, type4})
    self.assertEqual(set(pokemon_type_from_db.vulnerable_to.all()), {type2, type5})
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用