如何将一个 Django ModelForm CharField 渲染为选择框和文本框



我有一个 Django ModelForm,用于一个带有一组choicesCharField。我想为用户提供四个输入:我希望三个是带有选择选项的多项选择,最后一个是自由文本输入字段。有没有办法使用具有两种不同输入样式的字段来渲染一个ModelForm

我认为您正在寻求修改模型表单中使用的小部件。这里记录得很好。但是,这里有一个快速示例,应该是您要查找的。

class ExampleForm(forms.ModelForm):
    field_1 = forms.CharField(widget=forms.SelectMultiple(choices=FIELD_1_CHOICES))
    field_2 = forms.CharField(widget=forms.SelectMultiple(choices=FIELD_2_CHOICES))
    field_3 = forms.CharField(widget=forms.SelectMultiple(choices=FIELD_3_CHOICES))
    field_4 = forms.CharField(widget=forms.TextInput())
    class Meta:
        model = ExampleModel
        fields = ['field_1', 'field_2', 'field_3', 'field_4']

您需要为每个字段定义FIELD_1_CHOICES,并具有要提供的任何选项。另外,您不必为field_4行,因为TextInputCharField的默认小部件,但我添加了它以保持清晰。

您可以使用此自定义小部件来解决问题,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):
        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 myapp.fields import FormForm
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=_data_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
    })

最新更新