首页 文章

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

提问于
浏览
0

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

2 回答

  • 1

    我认为你已经很好地记录了here . 但是,这里's a quick example that should be what you'正在寻找 .

    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']
    

    你'll need to define the FIELD_1_CHOICES for each of the fields with whatever options you'喜欢给他们 . 此外,您不必为field_4执行该行,因为 TextInputCharField 的默认小部件,但我将其添加为清楚 .

  • 1

    你可以使用这个自定义小部件来解决问题,HTML5允许你有一个带有下拉列表的自由文本输入,这个列表可以作为pick-one-write-write-other类型的字段,这就是我的方法:

    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
        })
    

相关问题