Проектирование моделей Django: Соло-игрок ИЛИ команда с игроками в игре

Я разрабатываю веб-интерфейс на основе Django для игры, в которую можно играть как в одиночку, так и в команде. Игра основана на очках; побеждает та сторона, которая первой наберет заданное количество очков. Для последующей статистики и отображения, очки имеют временную метку.

Моя проблема: Как я могу иметь либо два Player ИЛИ два Team в одном Game? На данный момент мои модели выглядят следующим образом:

from django.db import models

# Create your models here.

class Player(models.Model):
    slug = models.SlugField(unique=True)    # will be autogenerated when inserting new Instance
    name = models.CharField(max_length=100)
    wins = models.IntegerField()
    losses = models.IntegerField()

    picture = models.ImageField(upload_to='images/player_pics')

    # games_played = wins + losses 

    def __str__(self):
        return self.name

class Team(models.Model):
    slug = models.SlugField(unique=True)
    name = models.CharField(max_length=100)
    players = models.ManyToManyField(Player)
    
    wins = models.IntegerField()    # from here on seems redundant to Player class
    losses = models.IntegerField() 

    picture = models.ImageField(upload_to='images/team_pics')

    # games_played = wins + losses 

    def __str__(self):
        return self.name


class Point(models.Model):
    val = models.IntegerField()
    timestamp = models.DateTimeField()


class Game(models.Model):
    slug = models.SlugField(unique=True)
    timestamp = models.DateTimeField()
    players = models.ManyToManyField(Player) # here should be either Team or Player
    points = models.ManyToManyField(Point)

Моя идея заключалась в том, чтобы реализовать другой класс типа GameParty, который может быть либо Player, либо Team, но там та же проблема. Мне также не нравятся избыточные поля, такие как победы и поражения.

Надеемся на ваш отзыв!

Вам не нужно жестко кодировать выигрыши, проигрыши и сыгранные партии, потому что вы можете получить эти значения с помощью запроса, используя внешние ключи и отношения "многие-ко-многим" (вы также можете создать динамическое свойство в вашей модели для возврата запроса, чтобы избежать повторений). Измените свои модели:

from django.db import models


class Player(models.Model):
    slug = models.SlugField(unique=True)
    name = models.CharField(max_length=100)
    picture = models.ImageField(upload_to='images/player_pics')

    def __str__(self):
        return self.name

class Team(models.Model):
    slug = models.SlugField(unique=True)
    name = models.CharField(max_length=100)
    players = models.ManyToManyField(Player)
    picture = models.ImageField(upload_to='images/team_pics')

    def __str__(self):
        return self.name


class Point(models.Model):
    player = models.ForeignKey(Player, on_delete=models.PROTECT, related_name='points') # You need to associate the player with the point
    val = models.IntegerField()
    timestamp = models.DateTimeField()


class Game(models.Model):
    slug = models.SlugField(unique=True)
    timestamp = models.DateTimeField()
    players = models.ManyToManyField(Player, related_name='games')
    points = models.ManyToManyField(Point)

Теперь, например, для получения игр, сыгранных игроком, можно написать такой запрос:

player = Player.objects.get(id=1)
games_played = player.games.count()

Или с динамическим свойством (это свойство не вставляется в базу данных, но оценивается при каждом вызове, поэтому вам не нужно его обновлять):

class Player(models.Model):
    # Your fields and methods
    @property
    def games_played(self):
        return self.games.count()

Для написания запросов возьмите ссылки из документации. Если вы хотите связать также команды с играми, вы можете создать дополнительную таблицу или использовать генеральное отношение.

Вернуться на верх