#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 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)]
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'
--
--
Ticket URL: <https://code.djangoproject.com/ticket/28443#comment:3>
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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/067.b033c456e2c67687702a238c9200cc91%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.