Reputation: 203
I'm trying to integrate with an inventory application and allow users to add parts to inventory through a Django form. I can read from the inventory database but have to write through the API so based on what they enter into the a previous form I want to give them a list of available parts to add.
Here is my form, I set a few choices just as a default:
class PartForm(forms.Form):
PART_CHOICES = (
('BT-J1KND-A', 'BT-J1KND-A'),
('BT-J1KND-B', 'BT-J1KND-B'),)
part = forms.ChoiceField(choices = PART_CHOICES,required = True, label = 'Part to add to Inventory')
And here is where I set the choices
parts_list = part_sql(part)
#build choices
PART_CHOICES= [(p[0],p[0]) for p in parts_list]
form = PartForm()
form.fields['part'].choices = PART_CHOICES
It displays correctly in the template but when I go to hit save and process the form if it is not one of the default choices I put in it says it is not a valid option.
Select a valid choice. BT-J1KND-C is not one of the available choices.
How do I fix this to get it to accept the choices I set as valid options?
Upvotes: 7
Views: 19511
Reputation: 3665
If you programmatically change one of the fields on a form, I believe you need to call full_clean()
on the form afterwards so that the changes get reflected in the form. We do this on an application I work on - here is the code we have modified for your example.
from django.forms import Select
...
field = form.fields['part']
field.choices = PART_CHOICES
field.widget = Select(choices=PART_CHOICES)
form.fields['part'] = field
form.full_clean()
Note that as well as assigning field.choices
, we also re-initialize field.widget
.
Upvotes: 0
Reputation: 343
Once the request gets processed, it seems that your user input goes into an unmodified PartForm
, using the hardcoded values.
In order to get the request processed correctly, you need to have a consistent PartForm
You can achieve this smoothly by modifying the field's choices
attribute at initialization.
For example:
class ExampleForm(forms.Form):
CHOICES = (
('EXMPL', 'Example'),
)
field = forms.ChoiceField(choices=CHOICES, required=True, label='Example')
def __init__(self, custom_choices=None, *args, **kwargs):
super(ExampleForm, self).__init__(*args, **kwargs)
if custom_choices:
self.fields['field'].choices = custom_choices
And then, just remember to initialize the form correctly, with
form = ExampleForm(my_custom_choices_nested_tuple, ...)
You may also double-check where you're actually processing data (a form = PartForm(request.REQUEST)
not mentioned in your copied code, I guess)
Upvotes: 14