我有两个模型,即“ Fixture”和“ PlayerVotes”。 PlayerVotes模型具有两个外键,即指向特定装置的链接和投票器(request.user)。
我想将整个灯具列表显示为可扩展的手风琴(bootstrap4),并允许已登录的用户为每个灯具实例提供一些投票。我不确定在哪里可以进行表单验证和save()函数。
models.py
class Fixture(models.Model):
season = models.PositiveIntegerField(blank=False, null=False,
validators=[
MinValueValidator(2019),
MaxValueValidator(datetime.now().year)])
round = models.PositiveIntegerField(blank=False, null=False)
game_time = models.DateTimeField(blank=True, null=True)
opponent = models.ForeignKey(Teams, on_delete=models.SET_NULL, null=True)
goals_for = models.PositiveIntegerField(null=True)
goals_againt = models.PositiveIntegerField(null=True)
def __str__(self):
return 'Round '+str(self.round)+ ' ('+str(self.season)+ ')'
class PlayerVotes(models.Model):
voter = models.ForeignKey(User,related_name="voter" ,on_delete=models.SET_NULL, null=True)
round = models.ForeignKey(Fixture, on_delete=models.SET_NULL, null=True)
three_votes = models.ForeignKey(User,related_name="three_votes" ,on_delete=models.SET_NULL, null=True)
two_votes = models.ForeignKey(User,related_name="two_votes" ,on_delete=models.SET_NULL, null=True)
one_vote = models.ForeignKey(User,related_name="one_vote", on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.voter+ '('+str(self.round) + ')'
forms.py
class PlayerVotesForm(forms.ModelForm):
class Meta:
model = models.PlayerVotes
fields = ('three_votes', 'two_votes', 'one_vote')
def __init__(self, user, round, *args, **kwargs):
self.voter = user
self.round = round
super(PlayerVotesForm, self).__init__(*args, **kwargs)
def clean(self):
all_clean_data = super().clean()
three_votes = all_clean_data['three_votes']
two_votes = all_clean_data['two_votes']
one_vote = all_clean_data['one_vote']
voter = all_clean_data['voter']
if three_votes == two_votes or three_votes == one_vote or two_votes == one_vote:
raise forms.ValidationError('You cannot vote for the same person twice!')
if voter == three_votes or voter == two_votes or voter == one_vote:
raise forms.ValidationError('You cannot vote for yourself!')
def save(self):
player_votes = super(PlayerVotesForm, self).save(commit=False)
player_votes.voter = self.voter
player_votes.round = self.round
search.save()
return search
views.py
@login_required
def votes(request):
fixtures = models.Fixture.objects.filter(season=datetime.today().year)
games = {}
for game in fixtures:
games[game.round] = [game.opponent, game.game_time, game.goals_for, game.goals_againt, forms.PlayerVotesForm(user=request.user, round=game)]
#form validation stuff goes here?
return render(request, 'votes/display.html', context={'games':games})
答案 0 :(得分:1)
使用邮寄请求提交表单时,表单验证已完成。您显示的代码用于呈现表单,您需要一个不同的视图来处理表单提交。您可以这样做:
__init__
def __init__(self, *args, **kwargs):
self.voter = kwargs.pop('user', None)
self.round = kwargs.pop('round', None)
super(PlayerVotesForm, self).__init__(*args, **kwargs)
# inside your votes view
for game in fixtures:
games[game] = forms.PlayerVotesForm(user=request.user, round=game)
return render(request, 'votes/display.html', context={'games':games})
{% for game, form in games.items %}
<h1> {{ game.round }} </h1>
...
<form action="{% url 'cast-vote' game.pk %}" method="post">
{{ form.as_p }}
<input type="submit" value="OK">
</form>
{% enfor %}
现在您需要处理上面给出的表单提交:
def cast_vote(request, pk):
game = get_object_or_404(Game, pk=pk)
if request.method == "POST":
form = PlayerVotesForm(request.POST, user=request.user, round=game)
if form.is_valid():
# do other logics
return redirect('votes-url')
path('castvote/<int:pk>/', cast_vote, name="cast-vote")