我正在创建一个包含Player
和Game
对象的排行榜应用。我使用自己的html代码创建了一个表单,而不是Django表单(在模板中看起来更好),您可以在其中添加一个以玩家1和玩家2以及各自目标命名的游戏。
如果我使用ModelForm
,它将检查值是否有效,但是由于表单输入是字符,但是模型对象游戏具有对象字段,因此查询无效。在尝试GameForm.is_valid
并使用输入的用户名从数据库中手动分配玩家之前,我曾尝试查询数据库,但出现此错误:
That choice is not one of the available choices.</li></ul></li><li>player2<ul class="errorlist"><li>Select a valid choice. That choice is not one of the available choices.</li></ul></li></ul>
[14/May/2019 20:08:04] "POST /elousers/elosearch/ HTTP/1.1" 200 9271
如何在不将表单设为ModelChoiceField
的情况下执行此操作?有替代方法还是应该完全尝试其他方法?
views.py
的表单(此表单上方还有第二个表单,因此我只提供了GameForm
的代码)
elif 'addgame' in request.POST:
data = request.POST.copy()
try:
player1 = Player.objects.get(name=data['player1'])
data['player1'] = player1
except Player.DoesNotExist:
render(request, 'elousers/elosearch.html',
{'game_display': "Player does not exist yet. Please Register"})
try:
player2 = Player.objects.get(name=data['player2'])
data['player2'] = player2
except Player.DoesNotExist:
render(request, 'elousers/elosearch.html',
{'game_display': "Player does not exist yet. Please Register"})
print(data)
request.POST.data = data
gameform = GameForm({'player1': data['player1'],
'player2': data['player2'],
'p1goal': data['p1goal'],
'p2goal': data['p2goal'],
})
print(gameform.errors)
if gameform.is_valid():
print("game form was valid")
gameform.save()
game_success = messages.success("Game Successfully Added!")
context2 = {'success': game_success}
return render(request, 'elousers/elosearch.html', context2)
else:
game_invalid = "Invalid entry. Please try again."
context2 = {'game_display': game_invalid}
return render(request, 'elousers/elosearch.html', context2)
forms.py
class GameForm(ModelForm):
player1 = forms.ModelChoiceField(queryset=Player.objects.all())
p1goal = forms.NumberInput()
player2 = forms.ModelChoiceField(queryset=Player.objects.all())
p2goal = forms.NumberInput()
class Meta:
model = Game
fields = (
'player1',
'p1goal',
'player2',
'p2goal',
)
def save(self, commit=True):
game = super(GameForm, self).save(commit=False)
game.player1 = self.cleaned_data['player1']
game.player2 = self.cleaned_data['player2']
game.p1goal = self.cleaned_data['p1goal']
game.p2goal = self.cleaned_data['p2goal']
player1 = Player.objects.get(name=game.player1)
player2 = Player.objects.get(name=game.player2)
new_game = Game(player1=player1, player2=player2, p1goal=game.p1goal, p2goal=game.p2goal)
# new_game.calculate()
if commit:
game.save()
# new_game.save()
return game
models.py
class Game(models.Model):
date_played = models.DateTimeField(default=timezone.now)
player1 = models.ForeignKey(Player, on_delete=models.CASCADE, related_name="+")
p1goal = models.IntegerField()
player2 = models.ForeignKey(Player, on_delete=models.CASCADE, related_name="+")
p2goal = models.IntegerField()
def __str__(self):
return str(self.date_played) + " - " + str(self.player1.name) + " " + str(self.p1goal) + " to " + \
str(self.p2goal) + " " + str(self.player2.name)
我模板中的html
<form method="post" prefix="expected">
{% csrf_token %}
<p><input class="w3-input w3-padding-16 w3-threequarter" style="margin-bottom:16px; border-bottom:1px solid black;" type="text" placeholder="Player 1" required name="player1"></p>
<p><input class="w3-input w3-padding-16 w3-quarter" style="margin-bottom:16px; border-left:16px solid black;border-bottom:1px solid black;" type="number" placeholder="Goals Scored" required name="p1goal"></p>
<p><input class="w3-input w3-padding-16 w3-threequarter" style="margin-bottom:16px; border-bottom:1px solid black;" type="text" placeholder="Player 2" required name="player2"></p>
<p><input class="w3-input w3-padding-16 w3-quarter" style="margin-bottom:16px; border-left:16px solid black;border-bottom:1px solid black;" type="number" placeholder="Goals Scored" required name="p2goal"></p>
<p>
我希望该表单为gameform.is_valid()
生成true,但事实并非如此,并且提早退出。我应该使用forms.form
而不是模型形式来避免被迫将用户名变成Player
对象吗?