MultiValueField не работает с ModelChoiceField

Код: (где 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» не имеет атрибута «выбор», потому что ModelChoiceField не объявлял его. Передача виджета в ModelChoiceField не работает, поскольку он создает копию, если это экземпляр. Таким образом, я установил атрибут выбора вручную, как вы можете видеть в закомментированном коде. Но затем я получил еще одну ошибку, которую не устранил: AttributeError: объект «RelatedFieldWidgetWrapper» не имеет атрибута «распаковать».


person Adam    schedule 27.07.2017    source источник


Ответы (1)


Вы хотите сделать это как виджет в Django?

<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')
    }
person Jayground    schedule 28.07.2017
comment
Нет, я добавил код виджета. Также я использую django 1.11, где вместо переопределения render вы можете использовать шаблоны и get_context - person Adam; 28.07.2017
comment
Я совершенно неправильно понял цель вашего вопроса. Вы решили свою проблему? Можете ли вы объяснить, что вы хотите построить более подробно? В методе распаковки вы уверены, что значение правильное ??? - person Jayground; 02.08.2017