Django ModelForms:将ManyToMany字段显示为单选

2023-12-26

在 Django 应用程序中,我有一个模型 Bet,其中包含与 Django 用户模型的 ManyToMany 关系:

class Bet(models.Model):
    ...
    participants = models.ManyToManyField(User)

用户应该能够使用表格开始新的投注。到目前为止,投注只有两个参与者,其中之一是自己创建投注的用户。这意味着在新投注的表格中,您必须选择一位参与者。保存表单数据后,投注创建者将被添加为参与者。

我正在使用 ModelFormNewBetForm:

class NewBetForm(forms.ModelForm):
    class Meta:
        model = Bet
        widgets = {
            'participants': forms.Select()
        }

    def save(self, user):
        ... # save user as participant

请注意参与者字段的重新定义小部件,它确保您只能选择一名参与者。

但是,这给了我一个验证错误:

Enter a list of values.

我不太确定这是从哪里来的。如果我查看开发人员工具中的 POST 数据,它似乎与我使用默认小部件并仅选择一名参与者完全相同。然而,似乎to_python()ManyToManyField 的方法在处理此数据时存在问题。如果我启用“选择”小部件,至少不会创建用户对象。

我知道我可以通过从表单中排除参与者字段并自己定义它来解决这个问题,但如果仍然可以使用 ModelForm 的功能,那就更好了(毕竟,这只是一个小部件更改)。如果我知道的话,也许我可以以某种方式操纵传递的数据。

谁能告诉我问题到底是什么以及是否有好的方法来解决它?

提前致谢!

Edit

正如评论中所建议的:视图的(相关)代码。

def new_bet(request):
    if request.method == 'POST':
        form = NewBetForm(request.POST)
        if form.is_valid():
            form.save(request.user)
            ... # success message and redirect
    else:
        form = NewBetForm()
    return render(request, 'bets/new.html', {'form': form})

深入研究 Django 代码后,我可以回答我自己的问题。

问题是 Django 的 ModelForm 映射ManyToManyField模型中的 s 为ModelMultipleChoiceField形式的 s。这种表单字段期望小部件对象从其对象返回一个序列value_from_datadict()方法。默认小部件为ModelMultipleChoiceField(这是SelectMultiple) 覆盖value_from_datadict()从用户提供的数据返回一个列表。但如果我使用Select小部件,默认value_from_datadict()使用超类的方法,它只返回一个字符串。ModelMultipleChoiceField根本不喜欢这样,因此验证错误。

我能想到的解决方案:

  1. 覆盖value_from_datadict() of Select通过继承或一些类装饰器。
  2. 通过创建新的表单字段并调整 m2m 字段来手动处理 m2m 字段save()的方法ModelForm将其数据保存在 m2m 关系中。

秒解决方案似乎不那么冗长,所以这就是我将要采用的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django ModelForms:将ManyToMany字段显示为单选 的相关文章

随机推荐