2023-05-06 18:57:45 +01:00

113 lines
3.4 KiB
Python

from django.db import models
from django.core.exceptions import ValidationError
# products/models.py
from django.db import models
class ReusableAutoField(models.PositiveIntegerField):
"""A django auto field that can reuse deleted primary keys"""
def get_next_available_id(self, model_cls, using=None):
"""
Returns the next available id for the given model class.
"""
all_ids = set(range(1, model_cls._default_manager.count()+1))
used_ids = set(model_cls._default_manager.all().values_list('pk', flat=True))
available_ids = all_ids - used_ids
if available_ids:
return min(available_ids)
if used_ids:
return max(used_ids) + 1
return 1
def get_default(self):
"""Returns the default value for this field"""
return self.get_next_available_id(self.model)
class Peg(models.Model):
"""Represents a person's peg"""
peg_number = ReusableAutoField(primary_key=True, default=ReusableAutoField.get_default, editable=False)
def __str__(self):
return f"Peg {self.peg_number}"
def validate_team_size(value):
if Member.objects.filter(team=value).count() >= 3:
raise ValidationError('Team already has maximal amount of members (3)')
class Member(models.Model):
"""Represents a member of a team"""
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
team = models.ForeignKey("Team", on_delete=models.SET_NULL, null=True, blank=True, validators=(validate_team_size,), related_name='members')
# peg = models.OneToOneField("Peg", on_delete=models.SET_NULL, null=True, blank=True)
def __str__(self):
return f"{self.first_name} {self.last_name} (team {self.team.team_number}))"
@property
def fullname(self) -> str:
return f"{self.first_name} {self.last_name}"
class Team(models.Model):
"""Represents a team"""
team_number = ReusableAutoField(primary_key=True, default=ReusableAutoField.get_default, editable=False)
section = models.OneToOneField("Section", on_delete=models.SET_NULL, null=True, blank=True)
def __str__(self):
return f"Team {self.team_number}"
@property
def members(self) -> list[Member]:
Member.objects.filter(team=self)
def validate_section_character(value):
"""Validates the section character"""
value = value.upper()
banned_characters = ["I"]
if value in banned_characters:
raise ValidationError(f"The character <{value}> is a prohibited character.")
class Section(models.Model):
"""Represents a section of the scoreboard"""
# character field stores a single character but doesnt allow for 'I' or 'i'
character = models.CharField(primary_key=True, max_length=1, validators=(validate_section_character, ))
def clean(self):
self.character = self.character.upper()
def __str__(self):
return f"Section {self.character}"
#class Scoreboard(models.Model):
# class Status(models.IntegerChoices):
# ACTIVE = 1, "Active"
# INACTIVE = 2, "Inactive"
# ARCHIVED = 3, "Archived"
#
# name = models.CharField(max_length=255)
# category = models.CharField(max_length=255)
# price = models.DecimalField(max_digits=10, decimal_places=2)
# cost = models.DecimalField(max_digits=10, decimal_places=2)
# status = models.PositiveSmallIntegerField(choices=Status.choices)
#
# def __str__(self):
# return self.name