#28443: MultiValueField does not work with ModelChoiceField?
---------------------------+--------------------------------------
     Reporter:  adam-kral  |                    Owner:  nobody
         Type:  Bug        |                   Status:  closed
    Component:  Forms      |                  Version:  1.11
     Severity:  Normal     |               Resolution:  needsinfo
     Keywords:             |             Triage Stage:  Unreviewed
    Has patch:  0          |      Needs documentation:  0
  Needs tests:  0          |  Patch needs improvement:  0
Easy pickings:  0          |                    UI/UX:  0
---------------------------+--------------------------------------
Description changed by adam-kral:

Old description:

> The code: (where AddressInput is a MultiWidget)
>
> {{{#!python
> 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)
> }}}
> I get this error: AttributeError: 'AddressInput' object has no attribute
> 'choices'
> Because ModelChoiceField did not declare it. Passing the widget to
> ModelChoiceField does not work as it makes a copy if it's an instance.
> Thus I set the choices attribute manually as you can see in the commented
> out code.
> But then I got another error which I didn't resolve: AttributeError:
> 'RelatedFieldWidgetWrapper' object has no attribute 'decompress'

New description:

 The code: (where AddressInput is a MultiWidget)

 {{{#!python
 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)]


 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)
 }}}
 I get this error: AttributeError: 'AddressInput' object has no attribute
 'choices'
 Because ModelChoiceField did not declare it. Passing the widget to
 ModelChoiceField does not work as it makes a copy if it's an instance.
 Thus I set the choices attribute manually as you can see in the commented
 out code.
 But then I got another error which I didn't resolve: AttributeError:
 'RelatedFieldWidgetWrapper' object has no attribute 'decompress'

--

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28443#comment:5>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/067.404f31899b55329935066b325bc382a1%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to