Reputation: 25
I'm designing a Django based webinterface for a game which can be played either solo OR as a team. A game is based on points; First party to reach set number of points wins. For later statistics and displaying, points have a timestamp.
My Problem: How can I have either two Player
s OR two Team
s in one Game
? My Models look like this at the moment:
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)
My Idea was to implement another class like GameParty
which can be either a Player
or a Team
but the same problem applies there. The redudant fields like wins and losses are also something I don't like.
Upvotes: 1
Views: 206
Reputation: 4191
You don' t need to hard code wins, loses and games played, because you can obtain these values with a query using foreign keys and many-to-many relationships (you can also create a dynamic property in your model to return the query to avoid repetitions). Change your models:
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)
Now for example to obtain games played by a player you can write this query:
player = Player.objects.get(id=1)
games_played = player.games.count()
Or with a dynamic property (this property is not inserted in the database but it is evaluated at each call, so you don' t need to update it):
class Player(models.Model):
# Your fields and methods
@property
def games_played(self):
return self.games.count()
To write queries take reference from the documentation. If you want to associate also teams with games, you can create an additional table or use a generic relation.
Upvotes: 0