Связывание экземпляра модели с экземпляром другой модели с использованием ModelForm - PullRequest
0 голосов
/ 11 апреля 2019

У меня есть две модели: «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

просмотров.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})

1 Ответ

1 голос
/ 11 апреля 2019

Проверка формы выполняется при отправке формы с использованием почтового запроса. Код, который вы показываете, предназначен для визуализации форм, вам нужно другое представление для обработки отправленных форм. Вы можете сделать это так:

Изменить форму __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})

Template

{% 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 %}

Теперь вам нужно обработать форму, указанную выше:

View

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')

URL

  path('castvote/<int:pk>/', cast_vote, name="cast-vote")
...