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?
Ordered by complexity DESC:
- Prepopulate it with all possible choices. For example, if you select player's id, it will be
choices = Player.objects.values_list('id', flat=True)
- Define it as
CharField
, but render it manually in template as select box. - Don't define it in form, but pass it's value to form's constructor (which you need to override to process this value.)
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.
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
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
]]
精彩评论