【问题标题】:MultiValueField does not work with ModelChoiceFieldMultiValueField 不适用于 ModelChoiceField
【发布时间】:2017-07-27 22:32:55
【问题描述】:

代码:(其中 AddressInput 是一个 MultiWidget)

class AddressInput(widgets.MultiWidget):
    def __init__(self, attrs=None):
        self.widgets = widgets.HiddenInput(attrs), widgets.TextInput(attrs) # note that the second widget would be customized, I'm only providing simplified example, which does produce the same error
        super().__init__(self.widgets, attrs)

    def decompress(self, value):
        try:
            address = AddressPoint.objects.get(pk=value)
        except (AddressPoint.DoesNotExist, ValueError):
            address = None

        return [value, str(address)]

    def value_from_datadict(self, data, files, name):
        return tuple(widget.value_from_datadict(data, files, f'{name}_{i}') for i, widget in enumerate(self.widgets))


class AddressFormField(MultiValueField):
    widget = AddressInput

    def __init__(self, queryset, empty_label="---------", to_field_name=None, limit_choices_to=None, *args, **kwargs):
        fields = (
            ModelChoiceField(queryset, empty_label=empty_label, to_field_name=to_field_name, limit_choices_to=limit_choices_to, *args, **kwargs),
            CharField()
        )

        super().__init__(fields=fields, require_all_fields=False, *args, **kwargs)

        #self.widget.choices = self.fields[0].widget.choices  #### if not commented out, I get another error: AttributeError: 'RelatedFieldWidgetWrapper' object has no attribute 'decompress'

    def compress(self, data_list):
        if not data_list[1]:
            return None

        if not data_list[0]:
            raise ValidationError('Invalid address')

        return data_list[0]


class AddressForeignKey(ForeignKey):
    def formfield(self, **kwargs):
        # This is a fairly standard way to set up some defaults
        # while letting the caller override them.
        defaults = {'form_class': AddressFormField}
        defaults.update(kwargs)
        return super().formfield(**defaults)

我收到此错误:AttributeError: 'AddressInput' object has no attribute 'choices' 因为 ModelChoiceField 没有声明它。将小部件传递给 ModelChoiceField 不起作用,因为如果它是一个实例,它会生成一个副本。 因此,正如您在注释掉的代码中看到的那样,我手动设置了选择属性。 但后来我遇到了另一个我没有解决的错误:AttributeError: 'RelatedFieldWidgetWrapper' object has no attribute 'decompress'

【问题讨论】:

    标签: python django django-forms django-1.11


    【解决方案1】:

    你想在 Django 中把它做成 Widget 吗?

    <input type="text" name="example" list="exampleList">
    <datalist id="exampleList">
      <option>hello</option>
      <option>there</option>
    </datalist>
    

    如果你这样做,你可以检查一下。

    class ListTextWidget(forms.TextInput):
        def __init__(self, data_list, name, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self._name = name
            self._list = data_list
            self.attrs.update({'list':'list_%s' % self._name, 'autocomplete':'off'})
    
        def render(self, name, value, attrs=None):
            text_html = super().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)
    
    
    class ExampleForm(ModelForm)
        ...
        include = ['exampleOne', ...]
        widgets = { 
        'exampleOne': ListTextWidget(data_list=yourModel.objects.all(),name='exampleOne')
        }
    

    【讨论】:

    • 不,我已经添加了小部件代码。我也在使用 django 1.11,而不是覆盖 render 你可以使用模板和 get_context
    • 我完全误解了你的问题的意图。你解决了你的问题吗?你能解释一下你想建立更多细节吗?在解压方法中,你确定值是正确的???
    猜你喜欢
    • 2019-11-16
    • 1970-01-01
    • 2014-11-15
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    相关资源
    最近更新 更多