我要寻找的是:单个小部件,它为用户提供了一个下拉选择列表,然后在其下方还有一个文本输入框,供用户输入新值。
后端模型将具有一组默认选项(但不会在模型上使用choices关键字)。我知道我可以(并且已经实现)通过将表单同时具有ChoicesField和CharField来实现这一点,并且如果ChoicesField保留为默认值,则代码可以使用CharField,但这感觉像“ un-django”。
有没有一种方法(使用Django-builtins或Django插件)为表单定义类似ChoiceEntryField(模仿IIRC的GtkComboboxEntry建模)的方法?
我会推荐一种自定义的Widget方法,HTML5允许你使用带有下拉列表的自由文本输入,该下拉列表可以用作“一键通”或“另一写”类型的字段,这就是我的方法:
fields.py
from django import forms class ListTextWidget(forms.TextInput): def __init__(self, data_list, name, *args, **kwargs): super(ListTextWidget, self).__init__(*args, **kwargs) self._name = name self._list = data_list self.attrs.update({'list':'list__%s' % self._name}) def render(self, name, value, attrs=None, renderer=None): text_html = super(ListTextWidget, self).render(name, value, attrs=attrs) data_list = '<datalist id="list__%s">' % self._name for item in self._list: data_list += '<option value="%s">' % item data_list += '</datalist>' return (text_html + data_list)
forms.py
from django import forms from myapp.fields import ListTextWidget class FormForm(forms.Form): char_field_with_list = forms.CharField(required=True) def __init__(self, *args, **kwargs): _country_list = kwargs.pop('data_list', None) super(FormForm, self).__init__(*args, **kwargs) # the "name" parameter will allow you to use the same widget more than once in the same # form, not setting this parameter differently will cuse all inputs display the # same list. self.fields['char_field_with_list'].widget = ListTextWidget(data_list=_country_list, name='country-list')
views.py
from myapp.forms import FormForm def country_form(request): # instead of hardcoding a list you could make a query of a model, as long as # it has a __str__() method you should be able to display it. country_list = ('Mexico', 'USA', 'China', 'France') form = FormForm(data_list=country_list) return render(request, 'my_app/country-form.html', { 'form': form })