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