ModelChoiceField在提交

时间:2016-01-01 14:02:12

标签: django django-models django-forms

以下是我的简单表单,其中包含一个ModelChoiceField

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

它允许用户从其中一个选项中选择(每个选项都表示为一个字符串)。当我选择一个选项并点击“提交”时,它会返回:

  

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

我的views.py看起来像这样:

from models import Property
from .forms import PropertyFilter

def index(request):
    if request.method == 'POST':
        form = PropertyFilter(request.POST)
        if form.is_valid():
            return HttpResponseRedirect('/')
    else:
        form = PropertyFilter()
        properties = Property.objects.all()
    return render(request, 'index.html',  context=locals())

我做错了什么?

1 个答案:

答案 0 :(得分:2)

ModelChoiceField的queryset参数不能是values_list,因为它会保存关系,所以django必须使用完整的模型对象,而不是模型对象的某些值。

如果要显示自定义选项文本,您应该以django方式自己定义一个简单的选择字段。您可以继承django表单ModelChoiceField并覆盖label_from_instance方法以返回要显示的文本:

class PropertyModelChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, obj):
         return obj.type

class PropertyFilter(forms.Form):
    type = PropertyModelChoiceField(queryset=Property.objects.all())

不相关的东西,但最好使用PropertyFilterForm作为表单名称,它会使您的代码更清晰。此外type是python中的保留字,因此请尝试使用其他字段来为您的字段名称property_type更好。

修改

我认为你(我也是)对你的初衷是多么困惑。您需要从所选内容中选择types Property,而不是Property个对象,因此您需要使用ChoiceField代替:

class PropertyFilter(forms.Form):
    type_choices = [(i['type'], i['type']) for i in Property.objects.values('type').distinct()]
    type = forms.ChoiceField(choices=type_choices)