Fix admin cascading delete

sync
Laurent 10 months ago
parent 852c0ff18c
commit f1eff69341
  1. 13
      sync/admin.py
  2. 34
      tournaments/admin.py
  3. 79
      tournaments/migrations/0099_alter_court_club_alter_dateinterval_event_and_more.py
  4. 5
      tournaments/models/club.py
  5. 3
      tournaments/models/court.py
  6. 3
      tournaments/models/date_interval.py
  7. 3
      tournaments/models/draw_log.py
  8. 8
      tournaments/models/event.py
  9. 13
      tournaments/models/group_stage.py
  10. 7
      tournaments/models/match.py
  11. 3
      tournaments/models/player_registration.py
  12. 3
      tournaments/models/purchase.py
  13. 8
      tournaments/models/round.py
  14. 8
      tournaments/models/team_registration.py
  15. 3
      tournaments/models/team_score.py
  16. 17
      tournaments/models/tournament.py

@ -3,13 +3,22 @@ from .models import BaseModel, ModelLog, DataAccess
from django.utils import timezone from django.utils import timezone
class AutoUpdateAdmin(admin.ModelAdmin): class SyncedObjectAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change): def save_model(self, request, obj, form, change):
if isinstance(obj, BaseModel): if isinstance(obj, BaseModel):
obj.last_updated_by = request.user obj.last_updated_by = request.user
obj.last_update = timezone.now() obj.last_update = timezone.now()
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
def delete_model(self, request, obj):
obj.delete_dependencies() # object must implement delete_dependencies(self)
obj.delete()
def delete_queryset(self, request, queryset):
for obj in queryset:
obj.delete_dependencies() # object must implement delete_dependencies(self)
queryset.delete()
class ModelLogAdmin(admin.ModelAdmin): class ModelLogAdmin(admin.ModelAdmin):
list_display = ['get_users', 'date', 'operation', 'model_id', 'model_name'] list_display = ['get_users', 'date', 'operation', 'model_id', 'model_name']
list_filter = ['users'] list_filter = ['users']
@ -19,7 +28,7 @@ class ModelLogAdmin(admin.ModelAdmin):
def get_users(self, obj): def get_users(self, obj):
return ", ".join([str(item) for item in obj.users.all()]) return ", ".join([str(item) for item in obj.users.all()])
class DataAccessAdmin(AutoUpdateAdmin): class DataAccessAdmin(SyncedObjectAdmin):
list_display = ['related_user', 'get_shared_users', 'model_name', 'model_id'] list_display = ['related_user', 'get_shared_users', 'model_name', 'model_id']
list_filter = ['related_user', 'shared_with'] list_filter = ['related_user', 'shared_with']
ordering = ['-granted_at'] ordering = ['-granted_at']

@ -7,7 +7,7 @@ from .models import Club, TeamScore, Tournament, CustomUser, Event, Round, Group
from .forms import CustomUserCreationForm, CustomUserChangeForm from .forms import CustomUserCreationForm, CustomUserChangeForm
from .filters import TeamScoreTournamentListFilter, MatchTournamentListFilter, SimpleTournamentListFilter, MatchTypeListFilter, SimpleIndexListFilter from .filters import TeamScoreTournamentListFilter, MatchTournamentListFilter, SimpleTournamentListFilter, MatchTypeListFilter, SimpleIndexListFilter
from sync.admin import AutoUpdateAdmin from sync.admin import SyncedObjectAdmin
class CustomUserAdmin(UserAdmin): class CustomUserAdmin(UserAdmin):
form = CustomUserChangeForm form = CustomUserChangeForm
@ -38,76 +38,76 @@ class CustomUserAdmin(UserAdmin):
obj.last_update = timezone.now() obj.last_update = timezone.now()
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
class EventAdmin(admin.ModelAdmin): class EventAdmin(SyncedObjectAdmin):
list_display = ['creation_date', 'name', 'club', 'creator', 'tenup_id'] list_display = ['creation_date', 'name', 'club', 'creator', 'tenup_id']
list_filter = ['creator', 'tenup_id'] list_filter = ['creator', 'tenup_id']
ordering = ['-creation_date'] ordering = ['-creation_date']
class TournamentAdmin(admin.ModelAdmin): class TournamentAdmin(SyncedObjectAdmin):
list_display = ['display_name', 'event', 'is_private', 'start_date', 'payment', 'creator'] list_display = ['display_name', 'event', 'is_private', 'start_date', 'payment', 'creator']
list_filter = ['is_deleted', 'event__creator'] list_filter = ['is_deleted', 'event__creator']
ordering = ['-start_date'] ordering = ['-start_date']
class TeamRegistrationAdmin(AutoUpdateAdmin): class TeamRegistrationAdmin(SyncedObjectAdmin):
list_display = ['player_names', 'group_stage_position', 'name', 'tournament'] list_display = ['player_names', 'group_stage_position', 'name', 'tournament']
list_filter = [SimpleTournamentListFilter] list_filter = [SimpleTournamentListFilter]
search_fields = ['id'] search_fields = ['id']
class TeamScoreAdmin(AutoUpdateAdmin): class TeamScoreAdmin(SyncedObjectAdmin):
list_display = ['team_registration', 'score', 'walk_out', 'match'] list_display = ['team_registration', 'score', 'walk_out', 'match']
list_filter = [TeamScoreTournamentListFilter] list_filter = [TeamScoreTournamentListFilter]
class RoundAdmin(AutoUpdateAdmin): class RoundAdmin(SyncedObjectAdmin):
list_display = ['tournament', 'name', 'index', 'parent'] list_display = ['tournament', 'name', 'index', 'parent']
list_filter = [SimpleTournamentListFilter, SimpleIndexListFilter] list_filter = [SimpleTournamentListFilter, SimpleIndexListFilter]
search_fields = ['id'] search_fields = ['id']
ordering = ['parent'] ordering = ['parent']
class PlayerRegistrationAdmin(AutoUpdateAdmin): class PlayerRegistrationAdmin(SyncedObjectAdmin):
list_display = ['first_name', 'last_name', 'licence_id', 'rank'] list_display = ['first_name', 'last_name', 'licence_id', 'rank']
search_fields = ('first_name', 'last_name') search_fields = ('first_name', 'last_name')
list_filter = [TeamScoreTournamentListFilter] list_filter = [TeamScoreTournamentListFilter]
ordering = ['last_name', 'first_name'] ordering = ['last_name', 'first_name']
class MatchAdmin(admin.ModelAdmin): class MatchAdmin(SyncedObjectAdmin):
list_display = ['__str__', 'round', 'group_stage', 'start_date', 'end_date', 'index'] list_display = ['__str__', 'round', 'group_stage', 'start_date', 'end_date', 'index']
list_filter = [MatchTypeListFilter, MatchTournamentListFilter, SimpleIndexListFilter] list_filter = [MatchTypeListFilter, MatchTournamentListFilter, SimpleIndexListFilter]
ordering = ['-group_stage', 'round'] ordering = ['-group_stage', 'round']
class GroupStageAdmin(admin.ModelAdmin): class GroupStageAdmin(SyncedObjectAdmin):
list_display = ['tournament', 'start_date', 'index'] list_display = ['tournament', 'start_date', 'index']
list_filter = [SimpleTournamentListFilter] list_filter = [SimpleTournamentListFilter]
ordering = ['-start_date', 'index'] ordering = ['-start_date', 'index']
class ClubAdmin(AutoUpdateAdmin): class ClubAdmin(SyncedObjectAdmin):
list_display = ['name', 'acronym', 'city', 'creator', 'events_count', 'broadcast_code'] list_display = ['name', 'acronym', 'city', 'creator', 'events_count', 'broadcast_code']
search_fields = ('name', 'acronym', 'city') search_fields = ('name', 'acronym', 'city')
ordering = ['creator'] ordering = ['creator']
class PurchaseAdmin(admin.ModelAdmin): class PurchaseAdmin(SyncedObjectAdmin):
list_display = ['id', 'user', 'product_id', 'quantity', 'purchase_date', 'revocation_date', 'expiration_date'] list_display = ['id', 'user', 'product_id', 'quantity', 'purchase_date', 'revocation_date', 'expiration_date']
list_filter = ['user'] list_filter = ['user']
ordering = ['-purchase_date'] ordering = ['-purchase_date']
class CourtAdmin(AutoUpdateAdmin): class CourtAdmin(SyncedObjectAdmin):
list_display = ['index', 'name', 'club'] list_display = ['index', 'name', 'club']
ordering = ['club'] ordering = ['club']
class DateIntervalAdmin(AutoUpdateAdmin): class DateIntervalAdmin(SyncedObjectAdmin):
list_display = ['court_index', 'event'] list_display = ['court_index', 'event']
class FailedApiCallAdmin(AutoUpdateAdmin): class FailedApiCallAdmin(admin.ModelAdmin):
list_display = ['date', 'user', 'type', 'error'] list_display = ['date', 'user', 'type', 'error']
list_filter = ['user'] list_filter = ['user']
class LogAdmin(AutoUpdateAdmin): class LogAdmin(admin.ModelAdmin):
list_display = ['date', 'user', 'message'] list_display = ['date', 'user', 'message']
list_filter = ['user'] list_filter = ['user']
class DeviceTokenAdmin(AutoUpdateAdmin): class DeviceTokenAdmin(admin.ModelAdmin):
list_display = ['user', 'value'] list_display = ['user', 'value']
class DrawLogAdmin(admin.ModelAdmin): class DrawLogAdmin(SyncedObjectAdmin):
list_display = ['tournament', 'draw_date', 'draw_seed', 'draw_match_index', 'draw_team_position'] list_display = ['tournament', 'draw_date', 'draw_seed', 'draw_match_index', 'draw_team_position']
list_filter = [SimpleTournamentListFilter] list_filter = [SimpleTournamentListFilter]
ordering = ['draw_date'] ordering = ['draw_date']

@ -0,0 +1,79 @@
# Generated by Django 5.1 on 2025-01-28 14:54
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0098_alter_drawlog_tournament'),
]
operations = [
migrations.AlterField(
model_name='court',
name='club',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='courts', to='tournaments.club'),
),
migrations.AlterField(
model_name='dateinterval',
name='event',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='date_intervals', to='tournaments.event'),
),
migrations.AlterField(
model_name='drawlog',
name='tournament',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='draw_logs', to='tournaments.tournament'),
),
migrations.AlterField(
model_name='groupstage',
name='tournament',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='group_stages', to='tournaments.tournament'),
),
migrations.AlterField(
model_name='match',
name='group_stage',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='matches', to='tournaments.groupstage'),
),
migrations.AlterField(
model_name='match',
name='round',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='matches', to='tournaments.round'),
),
migrations.AlterField(
model_name='playerregistration',
name='team_registration',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='player_registrations', to='tournaments.teamregistration'),
),
migrations.AlterField(
model_name='round',
name='parent',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='tournaments.round'),
),
migrations.AlterField(
model_name='round',
name='tournament',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rounds', to='tournaments.tournament'),
),
migrations.AlterField(
model_name='teamregistration',
name='tournament',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='team_registrations', to='tournaments.tournament'),
),
migrations.AlterField(
model_name='teamscore',
name='match',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='team_scores', to='tournaments.match'),
),
migrations.AlterField(
model_name='teamscore',
name='team_registration',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='team_scores', to='tournaments.teamregistration'),
),
migrations.AlterField(
model_name='tournament',
name='event',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tournaments', to='tournaments.event'),
),
]

@ -25,6 +25,11 @@ class Club(BaseModel):
court_count = models.IntegerField(default=2) court_count = models.IntegerField(default=2)
broadcast_code = models.CharField(max_length=10, null=True, blank=True, unique=True) broadcast_code = models.CharField(max_length=10, null=True, blank=True, unique=True)
def delete_dependencies(self):
for court in self.courts.all():
# court.delete_dependencies()
court.delete()
def __str__(self): def __str__(self):
return self.name return self.name

@ -10,6 +10,9 @@ class Court(BaseModel):
exit_allowed = models.BooleanField(default=False) exit_allowed = models.BooleanField(default=False)
indoor = models.BooleanField(default=False) indoor = models.BooleanField(default=False)
def delete_dependencies(self):
pass
def __str__(self): def __str__(self):
if self.name: if self.name:
return self.name return self.name

@ -8,3 +8,6 @@ class DateInterval(BaseModel):
court_index = models.IntegerField() court_index = models.IntegerField()
start_date = models.DateTimeField() start_date = models.DateTimeField()
end_date = models.DateTimeField() end_date = models.DateTimeField()
def delete_dependencies(self):
pass

@ -11,6 +11,9 @@ class DrawLog(SideStoreModel):
draw_team_position = models.IntegerField() draw_team_position = models.IntegerField()
draw_type = models.IntegerField(default=0) draw_type = models.IntegerField(default=0)
def delete_dependencies(self):
pass
def __str__(self): def __str__(self):
return f'{self.draw_date}' return f'{self.draw_date}'

@ -12,6 +12,14 @@ class Event(BaseModel):
tenup_id = models.CharField(max_length=20, null=True, blank=True) tenup_id = models.CharField(max_length=20, null=True, blank=True)
creator_full_name = models.CharField(max_length=200, null=True, blank=True) creator_full_name = models.CharField(max_length=200, null=True, blank=True)
def delete_dependencies(self):
for tournament in self.tournaments.all():
tournament.delete_dependencies()
tournament.delete()
for date_interval in self.date_intervals.all():
date_interval.delete_dependencies()
date_interval.delete()
def __str__(self): def __str__(self):
return self.display_name() return self.display_name()

@ -1,15 +1,15 @@
from asyncio.streams import StreamReaderProtocol # from asyncio.streams import StreamReaderProtocol
from django.db import models from django.db import models
from . import SideStoreModel, Tournament, FederalMatchCategory from . import SideStoreModel, Tournament, FederalMatchCategory
import uuid import uuid
from ..utils.extensions import format_seconds from ..utils.extensions import format_seconds
from datetime import datetime, timedelta # from datetime import datetime, timedelta
from django.utils import timezone from django.utils import timezone
class GroupStage(SideStoreModel): class GroupStage(SideStoreModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True)
tournament = models.ForeignKey(Tournament, on_delete=models.SET_NULL, related_name='group_stages', null=True) tournament = models.ForeignKey(Tournament, on_delete=models.SET_NULL, related_name='group_stages', null=True, blank=True)
index = models.IntegerField(default=0) index = models.IntegerField(default=0)
size = models.IntegerField(default=4) size = models.IntegerField(default=4)
format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True)
@ -17,6 +17,13 @@ class GroupStage(SideStoreModel):
name = models.CharField(max_length=200, null=True, blank=True) name = models.CharField(max_length=200, null=True, blank=True)
step = models.IntegerField(default=0) step = models.IntegerField(default=0)
def delete_dependencies(self):
for team_registration in self.team_registrations.all():
team_registration.delete_dependencies()
team_registration.delete()
for match in self.matches.all():
match.delete_dependencies()
match.delete()
def __str__(self): def __str__(self):
return self.display_name() return self.display_name()

@ -1,5 +1,5 @@
from django.db import models from django.db import models
from tournaments.models import group_stage # from tournaments.models import group_stage
from . import SideStoreModel, Round, GroupStage, FederalMatchCategory from . import SideStoreModel, Round, GroupStage, FederalMatchCategory
from django.utils import timezone, formats from django.utils import timezone, formats
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -27,6 +27,11 @@ class Match(SideStoreModel):
court_index = models.IntegerField(null=True, blank=True) court_index = models.IntegerField(null=True, blank=True)
confirmed = models.BooleanField(default=False) confirmed = models.BooleanField(default=False)
def delete_dependencies(self):
for team_score in self.team_scores.all():
# team_score.delete_dependencies()
team_score.delete()
def __str__(self): def __str__(self):
names = " / ".join(self.player_names()) names = " / ".join(self.player_names())
return f"{self.stage_name()} #{self.index}: {names}" return f"{self.stage_name()} #{self.index}: {names}"

@ -34,6 +34,9 @@ class PlayerRegistration(SideStoreModel):
source = models.IntegerField(choices=PlayerDataSource.choices, null=True, blank=True) source = models.IntegerField(choices=PlayerDataSource.choices, null=True, blank=True)
has_arrived = models.BooleanField(default=False) has_arrived = models.BooleanField(default=False)
def delete_dependencies(self):
pass
def __str__(self): def __str__(self):
return self.name() return self.name()

@ -12,5 +12,8 @@ class Purchase(models.Model):
revocation_date = models.DateTimeField(null=True, blank=True) revocation_date = models.DateTimeField(null=True, blank=True)
expiration_date = models.DateTimeField(null=True, blank=True) expiration_date = models.DateTimeField(null=True, blank=True)
def delete_dependencies(self):
pass
def __str__(self): def __str__(self):
return f"{self.id} > {self.product_id} - {self.purchase_date} - {self.user.username}" return f"{self.id} > {self.product_id} - {self.purchase_date} - {self.user.username}"

@ -12,6 +12,14 @@ class Round(SideStoreModel):
group_stage_loser_bracket = models.BooleanField(default=False) group_stage_loser_bracket = models.BooleanField(default=False)
loser_bracket_mode = models.IntegerField(default=0) loser_bracket_mode = models.IntegerField(default=0)
def delete_dependencies(self):
for round in self.children.all():
round.delete_dependencies()
round.delete()
for match in self.matches.all():
match.delete_dependencies()
match.delete()
def __str__(self): def __str__(self):
if self.parent: if self.parent:
return f"LB: {self.name()}" return f"LB: {self.name()}"

@ -30,6 +30,14 @@ class TeamRegistration(SideStoreModel):
final_ranking = models.IntegerField(null=True, blank=True) final_ranking = models.IntegerField(null=True, blank=True)
points_earned = models.IntegerField(null=True, blank=True) points_earned = models.IntegerField(null=True, blank=True)
def delete_dependencies(self):
for player_registration in self.player_registrations.all():
# player_registration.delete_dependencies()
player_registration.delete()
for team_score in self.team_scores.all():
# match.delete_dependencies()
team_score.delete()
def __str__(self): def __str__(self):
if self.name: if self.name:
return self.name return self.name

@ -10,6 +10,9 @@ class TeamScore(SideStoreModel):
walk_out = models.IntegerField(null=True, blank=True) # TODO type of WO: forfeit, injury... walk_out = models.IntegerField(null=True, blank=True) # TODO type of WO: forfeit, injury...
lucky_loser = models.IntegerField(null=True, blank=True) lucky_loser = models.IntegerField(null=True, blank=True)
def delete_dependencies(self):
pass
def __str__(self): def __str__(self):
return f"{self.match.stage_name()} #{self.match.index}: {self.player_names()}" return f"{self.match.stage_name()} #{self.match.index}: {self.player_names()}"

@ -66,6 +66,20 @@ class Tournament(BaseModel):
initial_seed_round = models.IntegerField(default=0) initial_seed_round = models.IntegerField(default=0)
initial_seed_count = models.IntegerField(default=0) initial_seed_count = models.IntegerField(default=0)
def delete_dependencies(self):
for team_registration in self.team_registrations.all():
team_registration.delete_dependencies()
team_registration.delete()
for gs in self.group_stages.all():
gs.delete_dependencies()
gs.delete()
for round in self.rounds.all():
round.delete_dependencies()
round.delete()
for draw_log in self.draw_logs.all():
# draw_log.delete_dependencies()
draw_log.delete()
def __str__(self): def __str__(self):
if self.name: if self.name:
return self.name return self.name
@ -166,7 +180,10 @@ class Tournament(BaseModel):
return self.end_date is None return self.end_date is None
def creator(self): def creator(self):
if self.event and self.event.creator:
return self.event.creator.username return self.event.creator.username
else:
return "--"
def private_label(self): def private_label(self):
if self.is_private: if self.is_private:

Loading…
Cancel
Save