According to Django docs., the ChoiceField accepts an iterable of two tuples, "or a callable that returns such an iterable" to use as choices for the field.
I've defined ChoiceFields
within my forms:
class PairRequestForm(forms.Form):
favorite_choices = forms.ChoiceField(choices=[], widget=RadioSelect, required=False)
Here is the view where I'm attempting to pass a tuple of custom choices:
class PairRequestView(FormView):
form_class = PairRequestForm
def get_initial(self):
requester_obj = Profile.objects.get(user__username=self.request.user)
accepter_obj = Profile.objects.get(user__username=self.kwargs.get("username"))
# `get_favorites()` is the object's method which returns a tuple.
favorites_set = requester_obj.get_favorites()
initial = super(PairRequestView, self).get_initial()
initial['favorite_choices'] = favorites_set
return initial
Within my models.py
, here is the method used above that returns a tuple:
def get_favorites(self):
return (('a', self.fave1), ('b', self.fave2), ('c', self.fave3))
From my understanding, if I want to pre-populate the form, I pass data in by overriding get_initial()
. I attempt to set the initial data of the form's favorite_choices
with a callable. The callable being favorites_set
.
With the current code, I am given an error of 'tuple' object is not callable
How can I pre-populate the RadioSelect ChoiceField with my own choices?
edit: I've also tried setting initial['favorite_choices'].choices = favorites_set
The get_initial
method is made to populate the initial value of the fields of your form. Not to set the available choices
or to modify your fields attributes.
To successfully passing your choices from your view to the form, you need to implement the get_form_kwargs
method in your view:
class PairRequestView(FormView):
form_class = PairRequestForm
def get_form_kwargs(self):
"""Passing the `choices` from your view to the form __init__ method"""
kwargs = super().get_form_kwargs()
# Here you can pass additional kwargs arguments to the form.
kwargs['favorite_choices'] = [('choice_value', 'choice_label')]
return kwargs
And in your form, get the choices from the kwargs argument in the __init__
method and set the choices on the field:
class PairRequestForm(forms.Form):
favorite_choices = forms.ChoiceField(choices=[], widget=RadioSelect, required=False)
def __init__(self, *args, **kwargs):
"""Populating the choices of the favorite_choices field using the favorites_choices kwargs"""
favorites_choices = kwargs.pop('favorite_choices')
super().__init__(*args, **kwargs)
self.fields['favorite_choices'].choices = favorites_choices
And voilà !
Another simple way of doing this would be:
class PairRequestView(FormView):
form_class = PairRequestForm
def get_form(self, *args, **kwargs):
requester_obj = Profile.objects.get(user__username=self.request.user)
favorites_set = requester_obj.get_favorites()
form = super().get_form(*args, **kwargs)
form.fields['favorite_choices'].choices = favorites_set
return form
You should encapsulate the choices in a proper parameter to the contructor of the form. Say you have a drop-down for 'groups' and you want to pass 'group choices':
class CreateAccountForm(forms.Form):
def __init__(self, groupChoices_, *args, **kwargs):
super(CreateAccountForm, self).__init__(*args, **kwargs)
self.fields['group'].choices = groupChoices_
group = forms.ChoiceField()
In your view, use groupChoices_ always as the 1st argument, e.g:
groupChoices = [
(2, 'A'),
(4, 'B'),
]
form = CreateAccountForm(groupChoices, request_.POST)
No need to worry about kwargs
horribleness!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With