使用ModelChoiceView时处理POST请求

时间:2016-01-03 11:39:27

标签: django django-forms

我的简单表格如下:

class PropertyFilterForm(forms.Form):
    property_type = forms.ModelChoiceField(queryset=Property.objects.values_list('type', flat=True).order_by().distinct())

property_type将字符串值的平面列表返回到模板的下拉列表中。

现在,当我选择其中一个值并点击"提交" - 我收到以下错误:

  

选择有效的选择。这种选择不是可用的选择之一   选择。

我此刻的观点如下:

def index(request):
    if request.method == 'POST':
        form = PropertyFilterForm(request.POST)
        if form.is_valid():
            selected_type = form.cleaned_data['property_type']
            properties = Property.objects.filter(type=selected_type)
    else:
        form = PropertyFilterForm()
        properties = Property.objects.all()
    return render(request, 'index.html',  context=locals())

我多次阅读并重读this question。这似乎是一回事,但我仍然无法弄清楚确切的解决方案。

到目前为止我所理解的是,每次在视图中调用它时,我都需要为我的表单显式指定一个查询集,或者(更好)在我的表单的init方法中指定查询集。

请有人详细说明我们是否需要按照上述方式指定查询集?

如果是,为什么?我们已经在表单定义中指定了它吗?

我会非常感谢任何代码片段

1 个答案:

答案 0 :(得分:0)

您希望用户选择字符串,而不是属性实例,因此我认为最好使用ChoiceField代替ModelChoiceField

class PropertyFilterForm(forms.Form):
    property_type = forms.ChoiceField(choices=[])

    def __init__(self, *args, **kwargs):
        super(PropertyFilterForm, self).__init__(*args, **kwargs)
        self.fields['property_type'].choices = Property.objects.values_list('type', 'type').order_by('type').distinct()

使用ChoiceField的缺点是我们需要在表单的__init__方法中生成选项。我们已经失去了ModelChoiceField的优秀功能,每次创建表单时都会评估查询集。

我不清楚为什么丹尼尔建议坚持ModelChoiceField而不是ChoiceField。如果您使用ModelChoiceField,我认为您必须将其子类化并覆盖label_from_instance。据我所知,使用values()无效。

要指定初始值,您可以在表单定义中对其进行硬编码,

class PropertyFilterForm(forms.Form):
    property_type = forms.ChoiceField(choices=[], initial='initial_type')

或在__init__方法中设置

self.fields['property_type'].initial = 'initial_type'

或在实例化表单时提供:

    form = PropertyFilterForm(request.POST, initial={'property_type': 'initial_type'})