From e6390fe6642cb8fbbe83553f059857a25b0bbafe Mon Sep 17 00:00:00 2001 From: bisco Date: Mon, 6 Apr 2026 19:26:07 +0200 Subject: [PATCH] refactor: move role and specialty ownership to player --- app/scouting/admin.py | 12 ++-- ...002_alter_team_unique_together_and_more.py | 56 +++++++++++++++++++ .../migrations/0003_alter_player_position.py | 18 ++++++ app/scouting/models.py | 34 ++++++----- 4 files changed, 96 insertions(+), 24 deletions(-) create mode 100644 app/scouting/migrations/0002_alter_team_unique_together_and_more.py create mode 100644 app/scouting/migrations/0003_alter_player_position.py diff --git a/app/scouting/admin.py b/app/scouting/admin.py index 99ba587..7d1361f 100644 --- a/app/scouting/admin.py +++ b/app/scouting/admin.py @@ -26,8 +26,10 @@ class SpecialtyAdmin(admin.ModelAdmin): @admin.register(Player) class PlayerAdmin(admin.ModelAdmin): - list_display = ("full_name", "nationality", "birth_date") + list_display = ("full_name", "position", "nationality", "birth_date") search_fields = ("full_name", "first_name", "last_name", "nationality") + list_filter = ("position",) + filter_horizontal = ("roles", "specialties") @admin.register(Competition) @@ -38,9 +40,8 @@ class CompetitionAdmin(admin.ModelAdmin): @admin.register(Team) class TeamAdmin(admin.ModelAdmin): - list_display = ("name", "competition", "country") + list_display = ("name", "country") search_fields = ("name", "country") - list_filter = ("competition",) @admin.register(Season) @@ -51,10 +52,9 @@ class SeasonAdmin(admin.ModelAdmin): @admin.register(PlayerSeason) class PlayerSeasonAdmin(admin.ModelAdmin): - list_display = ("player", "season", "team", "competition", "position") - list_filter = ("season", "competition", "position") + list_display = ("player", "season", "team", "competition") + list_filter = ("season", "competition") search_fields = ("player__full_name", "team__name", "competition__name") - filter_horizontal = ("roles", "specialties") @admin.register(PlayerSeasonStats) diff --git a/app/scouting/migrations/0002_alter_team_unique_together_and_more.py b/app/scouting/migrations/0002_alter_team_unique_together_and_more.py new file mode 100644 index 0000000..b2f6d78 --- /dev/null +++ b/app/scouting/migrations/0002_alter_team_unique_together_and_more.py @@ -0,0 +1,56 @@ +# Generated by Django 5.2.2 on 2026-04-06 17:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('scouting', '0001_initial'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='team', + unique_together=set(), + ), + migrations.RemoveField( + model_name='playerseason', + name='position', + ), + migrations.RemoveField( + model_name='playerseason', + name='roles', + ), + migrations.RemoveField( + model_name='playerseason', + name='specialties', + ), + migrations.AddField( + model_name='player', + name='position', + field=models.CharField(choices=[('PG', 'PG'), ('SG', 'SG'), ('SF', 'SF'), ('PF', 'PF'), ('C', 'C')], default='PG', max_length=2), + ), + migrations.AddField( + model_name='player', + name='roles', + field=models.ManyToManyField(blank=True, related_name='players', to='scouting.role'), + ), + migrations.AddField( + model_name='player', + name='specialties', + field=models.ManyToManyField(blank=True, related_name='players', to='scouting.specialty'), + ), + migrations.AddConstraint( + model_name='playerseason', + constraint=models.UniqueConstraint(fields=('player', 'season'), name='uniq_player_season'), + ), + migrations.AddConstraint( + model_name='team', + constraint=models.UniqueConstraint(fields=('name', 'country'), name='uniq_team_name_country'), + ), + migrations.RemoveField( + model_name='team', + name='competition', + ), + ] diff --git a/app/scouting/migrations/0003_alter_player_position.py b/app/scouting/migrations/0003_alter_player_position.py new file mode 100644 index 0000000..352f31a --- /dev/null +++ b/app/scouting/migrations/0003_alter_player_position.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.2 on 2026-04-06 17:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('scouting', '0002_alter_team_unique_together_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='player', + name='position', + field=models.CharField(choices=[('PG', 'PG'), ('SG', 'SG'), ('SF', 'SF'), ('PF', 'PF'), ('C', 'C')], max_length=2), + ), + ] diff --git a/app/scouting/models.py b/app/scouting/models.py index 54b6db0..ab35f96 100644 --- a/app/scouting/models.py +++ b/app/scouting/models.py @@ -26,6 +26,13 @@ class Specialty(models.Model): class Player(models.Model): + class Position(models.TextChoices): + PG = "PG", "PG" + SG = "SG", "SG" + SF = "SF", "SF" + PF = "PF", "PF" + C = "C", "C" + full_name = models.CharField(max_length=255) first_name = models.CharField(max_length=100, blank=True) last_name = models.CharField(max_length=100, blank=True) @@ -34,6 +41,9 @@ class Player(models.Model): height_cm = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) weight_kg = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) wingspan_cm = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) + position = models.CharField(max_length=2, choices=Position.choices) + roles = models.ManyToManyField(Role, blank=True, related_name="players") + specialties = models.ManyToManyField(Specialty, blank=True, related_name="players") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) @@ -60,20 +70,15 @@ class Competition(models.Model): class Team(models.Model): name = models.CharField(max_length=150) - competition = models.ForeignKey( - Competition, - on_delete=models.SET_NULL, - null=True, - blank=True, - related_name="teams", - ) country = models.CharField(max_length=100, blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["name"] - unique_together = ("name", "competition") + constraints = [ + models.UniqueConstraint(fields=["name", "country"], name="uniq_team_name_country"), + ] def __str__(self) -> str: return self.name @@ -94,13 +99,6 @@ class Season(models.Model): class PlayerSeason(models.Model): - class Position(models.TextChoices): - PG = "PG", "PG" - SG = "SG", "SG" - SF = "SF", "SF" - PF = "PF", "PF" - C = "C", "C" - player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name="player_seasons") season = models.ForeignKey(Season, on_delete=models.CASCADE, related_name="player_seasons") team = models.ForeignKey( @@ -117,14 +115,14 @@ class PlayerSeason(models.Model): blank=True, related_name="player_seasons", ) - position = models.CharField(max_length=2, choices=Position.choices) - roles = models.ManyToManyField(Role, blank=True, related_name="player_seasons") - specialties = models.ManyToManyField(Specialty, blank=True, related_name="player_seasons") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["player__full_name", "-season__start_year"] + constraints = [ + models.UniqueConstraint(fields=["player", "season"], name="uniq_player_season"), + ] def __str__(self) -> str: return f"{self.player.full_name} - {self.season.name}"