I'm trying to use a form with one field (shown as a dropdown in rendered template.html
) to change an attribute of multiple objects of the same model. However, for some reason I can't apply the retrieved form data to the objects.
models.py
:
class Player(models.Model):
class Race(models.TextChoices):
HUMAN = "Human"
UNDEAD = "Undead"
race = models.CharField(choices=Race.choices)
forms.py
:
class PlayerRaceForm(ModelForm):
class Meta:
model = Player
fields = [
'race'
]
views.py
:
def index(request):
players = Player.objects.all()
player_race_form = PlayerRaceForm()
if request.method == 'POST':
print(player_race_form.errors) # nothing here
print(player_race_form.non_field_errors) # see next code block
if player_race_form.is_valid(): # it aint for some reason :/
for player in players:
player.race = player_race_form.cleaned_data['race']
player.save()
context = {'player_race_form': player_race_form,}
return render(request, 'template.html', context)
On print(player_race_form.non_field_errors)
:
<bound method BaseForm.non_field_errors of <PlayerRaceForm bound=False, valid=False, fields=(race)>>
I tried to bypass the is_valid
and cleaned_data
and made it work somehow, but it saved a noticeably wrong value not in the Race
class.
def index(request):
players = Player.objects.all()
player_race_form = PlayerRaceForm()
if request.method == 'POST':
print(player_race_form.errors) # nothing here
print(player_race_form.non_field_errors) # see next code block
for player in players:
player.race = player_race_form['race'].value()
# player.race = player_race_form.data['race'] #MultiValueDictKeyError
player.save()
context = {'player_race_form': player_race_form,}
return render(request, 'template.html', context)
Also tried to modify one object only:
def index(request):
players = Player.objects.all()
player_race_form = PlayerRaceForm()
if request.method == 'POST':
print(player_race_form.errors) # nothing here
print(player_race_form.non_field_errors) # see next code block
if player_race_form.is_valid(): # it aint for some reason :/
player[0].race = player_race_form.cleaned_data['race']
player[0].save()
context = {'player_race_form': player_race_form,}
return render(request, 'template.html', context)
Still doesn't work.
While it's theoretically easy to just hack it by making a few if-else statements matching the value from the form to the actual value inside Race
, it's kinda wasteful to do so, so I'd like a Django way around this issue.