Django model design for tennis league - python

To learn web development, I'm developing a web app to help me manage our local tennis doubles league. We play once weekly, and it works like this:
Based on their rank, players are assigned to a court each week. The four players on each court play three Sets, changing partners for each Set. A team wins a Set by winning 6 games:
Set 1: Players 1 & 4 vs Players 2 & 3
Set 2: Players 1 & 3 vs Players 2 & 4
Set 3: Players 1 & 2 vs Players 3 & 4
After we finish, I evaluate the scores and recalculate each player's new rank.
Here are my Django models:
class Event(models.Model):
event_date = models.DateField()
class Player(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
class Set(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE)
team1_player1 = models.ForeignKey(
Player,
related_name='+',
on_delete=models.CASCADE)
team1_player2 = models.ForeignKey(
Player,
related_name='+',
on_delete=models.CASCADE)
team2_player1 = models.ForeignKey(
Player,
related_name='+',
on_delete=models.CASCADE)
team2_player2 = models.ForeignKey(
Player,
related_name='+',
on_delete=models.CASCADE)
team1_games_won = models.PositiveIntegerField(default=0)
team2_games_won = models.PositiveIntegerField(default=0)
At minimum, I have a couple of concerns:
In the Set model, the Player ForeignKey attributes caused reverse
accessor clashes, so I added related_name='+'.
If later I decide to retrieve a player's Set history, it would be nice to do something like this:
>>> p = Player.objects.get(id=1)
>>> p.sets.all()
But without the reverse accessor, it's not that simple.
I can make it work, but I'm wondering if there is a better way than my Set model?
Thanks

I would consider making a team object, with many to many relationships for the players on them. This would mean you now have 6 teams (ex. red yellow green blue indigo violet) that may also help with organization. Labeling each set as team_x_player_x is hard work to remember.
This is how I would do it.
Event:
date - datefield
sets - manytomanyfield # all the sets played that day
Set:
teams - manytomanyfield
winner - foreignfield
score - textfield (6-3)
Team:
name - textfield (to simplify ex team red vs team blue)
players - manytomanyfield
Player:
user - foreignfield
mmr - integer
Now you have a clearly defined hierarchy where an event has sets, sets have teams, and teams have players. It gets rid of the annoying issue you had with the related_name as well. You can now call player.team.all() and set all the teams that player plays on. You can also get team.set.all() to get all the sets each team has played in.

Related

How do I relate two table to know which value is included in ManyToMany field in Django?

Hope that the title is not as confusing as I thought it would be. I currently have a table for PaymentsData:
class PaymentsData(models.Model):
match = models.CharField(max_length=30)
amount = models.DecimalField(default = 0, max_digits = 5, decimal_places = 2)
players = models.ManyToManyField(Profile, blank=True)
playerspaid = models.ManyToManyField(Profile, related_name='paid', blank=True)
datespent = models.DateField('Date Spent')
def __str__(self):
return self.match
This field is used to create matches and include the number of players that played within players section and when they paid move them to playerspaid field.
What I wanted to do is using a different table, I wanted to present all the players individually, and include the matches that they need to pay for (which we can know by fetching the players in PaymentsData above). So it should look something similar to this:
class PlayersPaymentDetails(models.Model):
player = models.OneToOneField(Profile, on_delete=models.CASCADE)
matches = models.ManyToManyField(PaymentsData, blank=True)
amountdue = models.DecimalField(default = 0, max_digits=5, decimal_places = 2)
here in the matches, it should show all the matches that the player is selected in the players field within PaymentsData and the amountdue should show how much the player owes all together.
I have tried customising the model using the save() method, however when the players gets unselected from the PaymentsData, it does not change the PlayersPaymentDetails table.
Hope someone can help, Thanks. Do let me know if that's not clear.
Why do you need another table?
You can get the matches like so:
player = Profile.objects.get(...) # get the player you want
matches = player.paymentsdata_set.all()
and amountdue:
from django.db.models import Sum
player = Profile.objects.get(...) # get the player you want
amountdue = player.paymentsdata_set.all().aggregate(amountdue=Sum('amountdue'))['amountdue']

How to add another field in connection with a ManyToManyField?

class Team(models.Model):
college = models.CharField(max_length=20)
image = models.FileField(upload_to='documents/',null=True)
def __str__(self):
return self.college
class Athletics(Match):
time = ?
player = models.ManyToManyField(Player, related_name='player')
game_level = models.CharField(max_length=256, null=True, choices=LEVEL_CHOICES) # like semi-final, final etc
game_specific = models.CharField(max_length=256,null=True, choices=EVENT_CHOICES) #like Men's Shot Put or Men's Triple Jump etc
def __str__(self):
return str(self.game_level)
I am making an Athletics Sports Model for a sports tournament. I have an existing Player Model where I have listed players names and their teams. Now as you can see, I have added player field as ManyToManyField to choose for say 4-5 players match. Now I need finishing time for each player for judging who qualifies for the next round. Can it be possible to do this in this model only? Or I have to add another model? Help me!
You need an intermediate model between Player and Athletics to record information specific to the many-to-many relationship of the two models. Please read Extra fields on many-to-many relationships.
class PlayeAthletics(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
athletics = models.ForeignKey(Athletics, on_delete=models.CASCADE)
time = models.IntegerField()
class Athletics(Match):
player = models.ManyToManyField(Player, through='PlayerAthletics')

Django using many-to-one relationships

I'm completely new to Django web development and I'm having some issues using many to one relationships. I'm trying to complete a coding exercise in which I must develop a database for a game club where there will be a member list and a match list. the member list will store information pertaining to the member (eg. name, date they joined the club, matches won, matches lost, average score) and the match list will store data about each recorded match (eg. who player 1 and player 2 are, what date the match took place and what each players score was). What I was going to do was to use the many to one relationship to link multiple matches to a member and then have the match outcomes be information used to calculate Member information.
members/models.py:
from django.db import models
class Member(models.Model):
name = models.CharField(max_length=30)
match_wins = models.IntegerField()
match_losses = models.IntegerField()
date_joined = models.CharField(max_length=10)
average = models.IntegerField()
high_score = models.IntegerField()
matches/models.py:
from django.db import models
from members.models import Member
class Match(models.Model):
player1 = models.ForeignKey(Member, on_delete=models.CASCADE)
player2 = models.ForeignKey(Member, on_delete=models.CASCADE)
p1_score = models.IntegerField()
p2_score = models.IntegerField()
winner = ???(models.Member_id maybe?)
loser = ???
date = models.CharField(max_length=10)
As an example, how would I get match_wins in the Member class to be calculated via searching the matches attributed to member_id x and incrementing a value as per each win attributed to his id?
Same goes for the average value in the Member class, how would I query the matches attributed to member_id x again and increment a value per match played, sum the scores per each match and divide the result by the incremented value to get the average?
How would I do the comparison of each score attributed to member_id x to find the highest?
Also, on the Match side of things how do I get p1_score tied to player1 (same for player2) and get winner to compare the scores of player 1 and 2, then give the highest scoring player the win and the other player the loss?
Any help on this would be greatly appreciated as I am completely lost. Would it be easier to have Member and Match switched so that Member has the ForeignKey of a Match?
class Member(models.Model):
name = models.CharField(max_length=30)
match_wins = models.IntegerField()
match_losses = models.IntegerField()
date_joined = models.CharField(max_length=10)
average = models.IntegerField()
high_score = models.IntegerField()
class Match(models.Model):
player1 = models.ForeignKey(Member, related_name='games_as_player1', on_delete=models.CASCADE)
player2 = models.ForeignKey(Member, related_name='games_as_player2', on_delete=models.CASCADE)
p1_score = models.IntegerField()
p2_score = models.IntegerField()
winner = models.ForeignKey(Member, related_name='games_won')
loser = models.ForeignKey(Member, related_name='games_lost')
date = models.CharField(max_length=10)
player = Member.objects.get(pk=1)
player.games_won.count()
You also need to add related_name to the player1 and player2 fields so you can have multiple ForeignKeys to the same object.
Additionally, I would actually change the relationship to a Many To Many with possible additional information stored on the intermediary table, such as which player they were. This would remove the need for redundant fields. So maybe something like this:
class Member(models.Model):
name = models.CharField(max_length=30)
date_joined = models.CharField(max_length=10)
matches = models.ManyToManyField(Match, through='MemberMatch')
class MemberMatch(models.Model):
player = models.ForeignKey(Member)
match = models.ForeignKey(Match)
score = models.IntegerField()
won = models.BooleanField()
class Match(models.Model):
date = models.CharField(max_length=10)
And you could perform easy queries to get all the information I've removed from the classes.

Django Query including a table where no relation can be followed

i'm trying to 'join' this 4 models in a query. My starting point is a Team.id.
I am trying to get the SkillRecord into the result but i am completly lost.
class Team(models.Model):
user = models.ForeignKey(User)
id = models.IntegerField(primary_key=True, null=False, unique=True)
...
class Player(models.Model):
id = models.IntegerField(primary_key=True)
...
class Transfer(models.Model):
player = models.ForeignKey(Player)
seller = models.ForeignKey(Team, related_name='transfer_seller')
buyer = models.ForeignKey(Team, related_name='transfer_buyer')
date = models.DateTimeField()
...
class SkillRecord(models.Model):
player = models.ForeignKey(Player)
date = models.DateTimeField(default=datetime.datetime.now)
...
Here is my humble approach so far
def list_players(request, teamid):
team = get_object_or_404(Team, id=teamid)
players_transfers = Transfer.objects.filter(buyer=team).select_related('player')
I'm not really sure what would be my next step to get the SkillRecord model into the game.
I seem to lack the basic gist of those kind of problems so i will need a poke i guess.
Also, feel free to give me further ideas how to do this, i'm more or less sure i could also solve this whole Transfer thing using manytomanyfields or so.
Thanks a lot
To grab SkillRecord as well you need to add related_name:
class SkillRecord(models.Model):
player = models.ForeignKey(Player, related_name='skills')
date = models.DateTimeField(default=datetime.datetime.now)
then make the query:
qt = Transfer.objects.filter(...).select_related('player').prefetch_related('player__skills')
then retrieve them like so:
qt[0].player.skills.all()
Making some assumptions each Player has a Team so we can add.
class Player(models.Model):
team = models.ForeignKey(Team)
Then if you want the skillrecord start by there
SkillRecord.objects.filter(player__team=team)

Getting many to many fields of many to many association in django model

I have two levels of many to many associations in django. A player can belong to one or many teams. And a team can play one or many tournaments. Given a player i want to know in which all tournaments he has played.
Following is the simplified model:
class Tournament(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
class Team(models.Model):
team_name = models.CharField(max_length=100, blank=True, null=True)
tournaments_played = models.ManyToManyField(Tournament)
class Player(models.Model):
player_name = models.CharField(max_length=100, blank=True, null=True)
belongs_to_team = models.ManyToManyField(Team)
In my views i tried the following:
pl = Player.objects.get(player_name = "Andrew Flintoff")
ts = pl.belongs_to_team()
this gives me more than one team, now for each of the team i want to know which tournaments they have played.
qs_list = []
for t in ts:
team_qs = Team.objects.get(team_name = t)
tourn = team_qs.tournaments_played.all()
qs_list.append(tourn)
and then in my context i can pass the queryset list qs_list. Is there a better/simpler way of doing it??
p1_tournaments = Tournament.objects.filter(team__player=p1)
There's an implicit lookup created for every reverse foreign key or m2m field. It's either the lowercased model class or the related_name argument, if specified.
So, essentially, that filter says get the tournaments related to teams that are related to the player, p1.

Categories