Reputation: 41433
I'm using the forms framework and I'm using a but of javascript magic to inject some values on the fly into a select box (the values of this select box relies on a value form another).
Basically you have Team and Players. You need to define a player, but the players data comes from a Team.
In my form class i have
team = forms.ModelChoiceField(queryset=Team.objects.all()
player = forms.ChoiceField()
In the front end when the user selects a team from the select box, the (empty) players boxes gets correctly updated with new data. However when i hit submit, the player select box throws a error Select a valid choice. 2 is not one of the available choices.
2 IS a valid choice however.
Is there any way around this? Can i make the ChoiceField() take any value?
Upvotes: 1
Views: 2520
Reputation: 1
You can use the data parameter passed to init function to update choices dynamically.
class PlayerTeamForm(forms.ModelForm):
team = forms.ModelChoiceField(queryset=Team.objects.all()
player = forms.ChoiceField(choices = [])
class Meta:
model = PlayerTeamModel
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if kwargs.get('data'): # When form is submitted
# prefix for formsets
prefix = kwargs.get('prefix') + '-' if kwargs.get('prefix') else ''
player = Player.objects.get(
pk = kwargs.get('data').get(prefix + 'player')
)
self.fields['player'].choices = [[
player.pk, player.name
]]
else:
self.fields['player'].choices = [[
self.instance.player_id, self.instance.player.name
]]
Upvotes: 0
Reputation: 489
You can define the field as a CharField with forms.Select as the widget. That way the field is rendered as an empty select element and will accept any value.
player = forms.CharField(widget=forms.Select)
this is useful if you're using Select2 and loading values via ajax.
Upvotes: 3
Reputation: 5450
You could create your own ChoiceField, say DynamicChoiceField that extends from ChoiceField. You can then override the "clean" method to not do any validation as it would do with a regular ChoiceField.
class DynamicChoiceField(forms.ChoiceField):
def clean(self, value):
// Do whatever validation needs to happen
In the form, you could use DynamicChoiceField instead of ChoiceField
Upvotes: 1
Reputation: 31951
Ordered by complexity DESC:
choices = Player.objects.values_list('id', flat=True)
CharField
, but render it manually in template as select box.Upvotes: 3