带有 SelectMultiple 小部件的 MultipleChoiceField “值 [...] 不是有效选择。”

Posted

技术标签:

【中文标题】带有 SelectMultiple 小部件的 MultipleChoiceField “值 [...] 不是有效选择。”【英文标题】:MultipleChoiceField with SelectMultiple widget "Value [...] not a valid choice." 【发布时间】:2011-05-11 02:03:25 【问题描述】:

我的模型中定义了一个字段-

    languages = models.CharField(max_length = 30, choices=LANGUAGE_CHOICES, blank = True, null = True)

选择很简单-

LANGUAGE_CHOICES = (
    ('English', 'English'),
)

我在这个模型上定义了一个 ModelForm 并覆盖了字段-

languages = forms.MultipleChoiceField(choices=LANGUAGE_CHOICES, widget=forms.SelectMultiple)

当我填写表格时,选择“英文”,然后尝试提交,我得到一个错误-

语言 值 u"[u'English']" 不是一个有效的选择

我做错了什么基本的事情吗?或者 MultipleChoiceField 与 SelectMultiple 小部件结合不是可行的方法?

另外,为什么选择元组不能有两次相同的值,就像我现在有它一样('English','English')?

这里有一些额外的代码可能有助于深入了解这一点

模板代码:

<div class="abovepad">
<label for="id_languages">Languages:</label>
    form.languages
</div>

POST 数据的语言部分:

u'languages': [u'English'],

ModelForm相关sn-p代码:

class ProfileForm(forms.ModelForm):        
languages = forms.MultipleChoiceField(choices=LANGUAGE_CHOICES)
class Meta:
    model = Student

如你所见,我几乎没有定制任何东西。过去,当我遇到这个问题时,我会切换到将列表中的项目转换为模型,然后使用不会导致相同问题的 ManyToMany 字段。对于这些情况,让项目成为模型是有意义的;在这种情况下它没有。我只想知道我是否做错了什么,或者这个组合是否应该起作用。如果没有真正的答案,那么我的另一个选择是尝试挖掘 Django 表单代码,看看它为什么会这样做。

【问题讨论】:

【参考方案1】:

错误消息表明languages 不包含数组,而是包含包含该数组表示的 unicode 字符串。 languages 应计算为 [u'English'](数组),但计算结果为 u"[u'English']"(unicode 字符串)。

您的 ModelForm 是否包含任何可能会更改 languages 值的自定义验证(例如,clean_languages 函数)?

顺便说一句:SelectMultiple 已经是 MultipleChoiceField 的默认小部件,因此无需指定小部件。

一些有助于找到原因的事情:

呈现表单的模板代码 表单返回的POST数据 用于 ModelForm 类的代码

【讨论】:

感谢乔丹,您的及时回复。我在上面发布了相关的信息。我的 ModelForm 不包含任何额外的内容,不幸的是,摆脱显式的小部件参数也无济于事。在我看来,Django 表单验证代码出于某种原因将 POST 数据中的数组转换为字符串...【参考方案2】:

我知道这一点已经一年多了,但我认为尝试回答可能仍然会有所帮助。

我认为这里可能存在几个问题,但主要问题是 ModelForm 期望数据库记录的键而不是字符串值。

如果您制作的表单与您的数据库无关,我建议您制作表单而不是 ModelForm。但是,如果您确实想与数据库进行交互,请使用 ModelForm 并在 Student 模型中定义一个 ForeignKey 以与语言表相关联,让 ModelForm 为您完成工作。

基于我对您的模型的假设的示例应用。

your_project/example_app/models.py:

from django.db import models

class Student(models.Model):
    name = models.CharField(max_length=255)
    language = models.ForeignKey('Language')

class Language(models.Model):
    name = models.CharField(max_length=255)

your_project/example_app/forms.py:

from django.forms import ModelForm
from example.models import Student

class StudentForm(ModelForm):
    class Meta:
        model = Student

相关文档:https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#modelform

sn-p:

如您所料,ForeignKey 和 ManyToManyField 模型字段类型是特殊情况:

ForeignKey 由django.forms.ModelChoiceField 表示,它是一个ChoiceField,其选择是一个模型QuerySet。 ManyToManyField 由django.forms.ModelMultipleChoiceField 表示,它是一个MultipleChoiceField,其选择是一个模型QuerySet。

【讨论】:

+1 对于文档中的 sn-p,它帮助我解决了一个不相关的问题,因为在 ManyToManyField 上意外使用了 ModelChoiceField 而不是 ModelMultipleChoiceField【参考方案3】:

您必须从您的模型 定义中删除choices=LANGUAGE_CHOICES: 您的表单返回的是所选值的列表,这在您的 models.LANGUAGE_CHOICES 中不存在

【讨论】:

我很惊讶这个答案没有得到应有的关注。我遇到了与 OP 完全相同的问题,这个答案为我节省了数小时的调试时间!

以上是关于带有 SelectMultiple 小部件的 MultipleChoiceField “值 [...] 不是有效选择。”的主要内容,如果未能解决你的问题,请参考以下文章

是否有与 HTML 中的“选择多个”元素等效的小部件

如何在 Django 表单中添加新的相关对象

带有下拉列表的android按钮小部件,这个特定小部件的名称是啥?

php 带有图像场图像小部件的小部件

Flutter/Dart:我的小部件树中可以有多个带有状态的小部件吗?

带有参数的今日小部件 openurl