как я могу установить связь между двумя полями с разными классами django?

#python #django

#python #django

Вопрос:

у меня есть две модели «Club» class и «Match» class, и у него есть внешний ключ для Club, но я не могу увеличить поле «won» (или draw или lost) в классе «Club» на «score_local» и «score_visitor» в классе «Match» .. как я могу это сделать

 class Club(models.Model):
    league_names = models.ForeignKey(League, on_delete= models.CASCADE, related_name='club')
    name = models.CharField(max_length=100)
    logo = models.ImageField(upload_to='media/core', max_length=255, null=True, blank=True)
    year_of_establishment = models.IntegerField(default=1900)
    won = models.IntegerField(default=0)
    draw = models.IntegerField(default=0)
    lost = models.IntegerField(default=0)

    def CalcPoints(self):
         return self.won*3   self.draw            

    total_points = property(CalcPoints)

class Match(models.Model):
    play_date = models.DateTimeField('play date')
    occasion = models.ForeignKey(League, on_delete=models.CASCADE, related_name='match')
    club_visitor = models.ForeignKey(Club, on_delete=models.CASCADE, related_name='match_club_visitor')
    club_local = models.ForeignKey(Club, on_delete=models.CASCADE, related_name='match_club_local')
    score_visitor = models.IntegerField()
    score_local = models.IntegerField()
  

Комментарии:

1. можете ли вы более подробно объяснить, какова связь между «выигранным», «ничьей», «проигранным», «score_visitor» и «score_local»?

2. я хочу сделать что-то вроде этого score_visitor (для club_local) и score_visitor (для club_visitor) score_visitor > score_local ====> club_visitor.выиграл 1 и club_local. потеряно 1

3. Откуда вы знаете, что игра завершена? Это post-запрос, который вы выполняете?

4. до сих пор я стараюсь только вводить результаты и возвращать счет и очки каждому клубу и подсчитывать очки…..

Ответ №1:

Вы не можете установить связь между полями to даже в одной и той же модели, но вы можете переопределить save метод в Match вы могли бы реализовать обработчик сигнала, который вызывается после каждого match сохранения.

 @receiver(post_save, sender=Match)
def update_club_score(sender, instance, **kwargs):
    # Local won.
    if instance.score_local > instance.score_visitor:
        instance.club_local.won  = 1
        instance.club_local.save()
        instance.club_visitor.lost  = 1
        instance.club_visitor.save()
    # Local lost.
    if instance.score_local < instance.score_visitor:
        instance.club_visitor.won  = 1
        instance.club_visitor.save()
        instance.club_local.lost  = 1
        instance.club_local.save()
    # Draw
    if instance.score_local == instance.score_visitor:
        instance.club_local.draw  = 1
        instance.club_local.save()
        instance.club_visitor.draw  = 1
        instance.club_visitor.save()
  

Комментарии:

1. @omarahmed Хорошо, пожалуйста, всегда не забывайте голосовать или / и выбирать ответы, которые помогают.

Ответ №2:

Вам нужно будет как-то обновить поля ваших моделей.

Я бы предложил что-то вроде:

Сначала напишите функцию, которая получает вам клубы из базы данных:

 def get_clubs(local_club_id, visitor_club_id):
    local_club = Club.objects.filter(pk=self.local_club_id)[0]
    visitor_club = Club.objects.filter(pk=self.visitor_club_id)[0]
    return local_club, visitor_club
  

И затем вы можете соответствующим образом обновить выигрыши и проигрыши (в вашем views.py ):

 def update_scores(request):
    match = request.match
    club_local, club_visitor = get_clubs(match.club_local.pk, match.club_visitor.pk)
    if match.score_local > match.score_visitor:
        # home team won
        club_local.update(won=match.club_local.won   1)
        club_visitor.update(lost=match.club_visitor.lost   1)
    elif match.score_visitor > match.score_local:
        # away team won
        club_visitor.update(won=match.club_visitor.won   1)
        club_local.update(lost=match.club_local.lost   1)
    else:
        # it's a draw
        club_local.update(draw=match.club_local.draw   1)
        club_visitor.update(draw=match.club_visitor.draw   1)
  

После этого ваша функция свойств должна работать должным образом.

Комментарии:

1. Это не лучший способ сделать это, вы каждый раз просматриваете весь список совпадений. Когда совпадение заканчивается, просто обновите связанные с ним клубы. Просто.

2. Более подходящий способ — это то, что @andreihondrari указывает в своем ответе (переопределяя сохранение) или обработчиком сигналов, подобным моему.

3. просто я хочу обновить «выигранные» (потерянные или нарисованные) поля после добавления нового соответствия .. я пытался использовать сигнал post_save, но все еще не работает.. сначала я добавил эту функцию в класс «Match», чтобы определить точки (self): если self.score_local > self.score_visitor: return (self.club_local.won) 1 и (self.club_visitor.lost) 1, если self.score_local <self.score_visitor: return (self.club_local.lost) 1 и (self.club_visitor.won) 1 еще: возврат (self.club_local.draw) 1 и (self.club_visitor.draw) 1 post_save.connect(Club.teampoints, отправитель = Совпадение)

4. да, ofc. нет необходимости каждый раз перебирать все игры (это также приведет к неправильным результатам). Однако это было просто примером того, как будет работать запрос на обновление. Вы можете сделать вышеуказанное как функцию и вызвать ее только после завершения игры.