Django - 选择一个有效的选项。该选择不是可用的选择之一

Posted

技术标签:

【中文标题】Django - 选择一个有效的选项。该选择不是可用的选择之一【英文标题】:Django - Select a valid choice. That choice is not one of the available choices 【发布时间】:2018-06-11 00:03:40 【问题描述】:

这是我的表格:

class RoleForm(forms.ModelForm):
    class Meta:
        model = models.RoleModel
        fields = ['name']

class FeatureForm(forms.ModelForm):
    role = forms.ModelChoiceField(queryset=models.RoleModel.objects.values_list('name', flat=True).distinct())
    class Meta:
        model = models.FeatureModel
        fields = ['role','feature']

在我的引导表单中,选项显示正确。我得到所有角色的列表。但是,如果我填写功能表单并点击提交,它会显示 - “选择一个有效的选择。该选择不是可用的选择之一。”

我的模型是:

class RoleModel(models.Model):
    name = models.CharField(validators=[alphanumeric], max_length=50, unique=True, blank=False)

class FeatureModel(models.Model):
    role = models.ForeignKey(RoleModel, on_delete=models.PROTECT)
    feature = models.CharField(validators=[alphanumeric], max_length=10, unique=True)

我的 bootsrtap 形式是:

<form action="% url 'feature_form' %" novalidate method="POST">% csrf_token %         
            <div class="row">
                <div class="col">
                <label for="role"> fform.role.label </label>
                <p><select class="form-control id="role" name="role">
                % for item in fform.role %
                 item 
                % endfor %
                </select></p>
                % for error in fform.role.errors %
                <p><small class="alert-danger"> error </small></p>
                % endfor %
                </div>

                <div class="col">
                <label for="feature"> fform.feature.label </label>
                <p><input type="text" class="form-control" id="feature" name="feature"
                % if fform.feature.value is not None %
                value=" fform.feature.value "
                % endif %
                ></p>
                % for error in fform.feature.errors %
                <p><small class="alert-danger"> error </small></p>
                % endfor %
                </div>
            </div>

            <input class='btn btn-primary btn-sm' type='submit' value='Save'>                
        </form>

我的需求很简单。第二种形式(FeatureForm)有两个字段。角色是另一个模型的外键和一个用于输入特征名称的文本字段。在我的客户端,我需要将外键显示为带有列表的选择选项。我从这个选择中选择了一个值,输入特征的值并点击保存。它必须保存。

【问题讨论】:

【参考方案1】:

它不起作用,因为您的查询集仅包含名称,但您需要 RoleModel 的 id / 主键。由于您的选择没有 ID,因此它们不是有效的选择。

首先,您的 RoleModel name 设置为 unique,因此查询 distinct() 名称值没有意义,因为它们在唯一的定义中已经不同了。

您也不需要构建自己的选择输入。 Django 会处理这个。

你只需要:

class RoleModel(models.Model):
    name = models.CharField(validators=[alphanumeric], max_length=50, unique=True, blank=False)

    def __str__(self):
         return self.name

class FeatureForm(forms.ModelForm):
    class Meta:
        model = models.FeatureModel
        fields = ['role', 'feature']

    def __init__(self, *args, **kwargs):
        super(FeatureForm, self).__init__(*args, **kwargs)
        for field in self.fields:
            self.fields[field].widget.attrs = 'class': 'form-control'

<form action="% url 'feature_form' %" novalidate method="POST">
    % csrf_token %         
    <div class="row">
        <div class="col">
            <label for="role"> fform.role.label </label>
            <p> fform.role  </p>
            % for error in fform.role.errors %
            <p><small class="alert-danger"> error </small></p>
            % endfor %
        </div>
        <div class="col">
            <label for="feature"> fform.feature.label </label>
            <p> fform.feature </p>
            % for error in fform.feature.errors %
            <p><small class="alert-danger"> error </small></p>
            % endfor %
        </div>
    </div>
    <input class='btn btn-primary btn-sm' type='submit' value='Save'>                
</form>

编辑:否则,本例中的 Select 输入应构造为:

<select>
    <option value="1">Name 1</option>
    <option value="2">Name 2</option>
</select>

其中value 是一个ID,在您的情况下是RoleModel 的主键。您的选择选项没有此值。

【讨论】:

感谢您的回复。这样它就可以保存数据。但是,在客户端的选择选项中,我没有得到值,而是显示为 RoleModel 对象(3)。我们如何调整它以使选择显示值而不是对象? str 添加到RoleModel。我已经编辑了我的答案。 这就像一个魅力。谢谢你。至于我了解特征形式的init函数究竟做了什么? init 旨在将对象实例自定义为特定的初始状态。在这种情况下,它用于向字段添加属性类,因此您不必在小部件 Meta 选项中单独为每个字段添加表单控件,甚至无需在模板中使用模板标签。

以上是关于Django - 选择一个有效的选项。该选择不是可用的选择之一的主要内容,如果未能解决你的问题,请参考以下文章

选择一个有效的选择 Django Filtered Drop Down Menu

text select2 django选择有效的选项选项错误

检查特定实例是不是存在的更好选择 django

在 Django 中检索多个选择选项时出错

Django Jquery:基于选择,显示更多选择选项

Django-Select2 重型小部件