我的简单表格如下:
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方法中指定查询集。
请有人详细说明我们是否需要按照上述方式指定查询集?
如果是,为什么?我们已经在表单定义中指定了它吗?
我会非常感谢任何代码片段
答案 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'})