Closed davidcr01 closed 1 year ago
A new model and serializer have been added to manage the participation:
class Participation(models.Model):
tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE)
player = models.ForeignKey(Player, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['tournament', 'player'],
name='unique_participation'
)
]
The model specifies the combination of the tournament and the player as unique. This combination is not specified as the primary key for performance purposes.
About the view, is necessary to check some conditions in the POST request:
Besides, when creating the participation, a new notification must be created and associated to the player. All of this is controlled in this code snippet:
def create(self, request, *args, **kwargs):
tournament_id = request.data.get('tournament_id')
player = request.user.player
# Request tournament_id field
if not tournament_id:
return Response({'error': 'tournament_id field is required.'}, status=404)
# Check if the user is a player
if not player:
return Response({'error': 'Player not found'}, status=404)
# Case of non existing tournament
try:
tournament = Tournament.objects.get(id=tournament_id)
except Tournament.DoesNotExist:
return Response({'error': 'Invalid tournament ID'}, status=400)
# Case of existing participation
if Participation.objects.filter(tournament_id=tournament_id, player=player).exists():
return Response({'error': 'You are participating in this tournament.'}, status=status.HTTP_400_BAD_REQUEST)
# Case of the tournament is closed
if tournament.is_closed:
return Response({'error': 'Tournament is closed for participation'}, status=400)
# Close the tournament if is full
if tournament.num_players >= tournament.max_players:
tournament.is_closed = True
tournament.save()
return Response({'error': 'Tournament is already full'}, status=400)
participation = Participation.objects.create(tournament=tournament, player=player)
tournament.num_players += 1
# Close the tournament if is full
if tournament.num_players >= tournament.max_players:
tournament.is_closed = True
tournament.save()
# Create the related notification to the player
message = f"You were assigned in {tournament.name}. Good luck!"
link = "http://localhost:8100/tabs/tournaments"
notification = Notification.objects.create(player=player, text=message, link=link)
notification.save()
serializer = self.get_serializer(participation)
return Response(serializer.data, status=201)
In case of the GET request, we filter the participations by the tournament_id
parameter, which is requested.
def list(self, request):
tournament_id = int(request.query_params.get('tournament_id'),10)
if not tournament_id:
return Response({'error': 'tournament_id parameter is required.'}, status=status.HTTP_400_BAD_REQUEST)
queryset = self.get_queryset().filter(tournament_id=tournament_id)
serializer = self.serializer_class(queryset, many=True)
return Response(serializer.data)
In the Admin site, the same logic must be implemented. Besides, is necessary to modify the num_players
field of the tournament when creating (save_model
) or deleting (either single delete (delete_model
) or multiselection delete delete_queryset
)
class TournamentAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'description', 'num_players', 'max_players', 'word_length', 'is_closed')
form = TournamentsForm
class ParticipationAdmin(admin.ModelAdmin):
model = Participation
list_display = ('id', 'tournament', 'player',)
list_filter = ('tournament',)
# Checks if a new participation can be added
def save_model(self, request, obj, form, change):
tournament = obj.tournament
if (tournament.num_players >= tournament.max_players):
raise forms.ValidationError("The max number of participations for this tournament has been reached.")
tournament.num_players += 1
if (tournament.num_players >= tournament.max_players):
tournament.is_closed = True
tournament.save()
super().save_model(request, obj, form, change)
player = obj.player
message = f"You were assigned in {tournament.name}. Good luck!"
link = "http://localhost:8100/tabs/tournaments"
notification = Notification.objects.create(player=player, text=message, link=link)
notification.save()
# Decreases the number of the players of the tournament
def delete_model(self, request, obj):
tournament = obj.tournament
tournament.num_players -= 1
if tournament.num_players < tournament.max_players:
tournament.is_closed = False
tournament.save()
super().delete_model(request, obj)
# Updates the number of players when using the multi-selection
def delete_queryset(self, request, queryset):
tournaments = set()
for participation in queryset:
tournaments.add(participation.tournament)
super().delete_queryset(request, queryset)
for tournament in tournaments:
num_participations = Participation.objects.filter(tournament=tournament).count()
tournament.num_players = num_participations
if num_participations >= tournament.max_players:
tournament.is_closed = True
else:
tournament.is_closed = False
tournament.save()
The following video shows an administrator:
https://github.com/davidcr01/WordlePlus/assets/72193239/39e57d0b-7087-4b07-aa02-ad535ff2afd5
The following video shows:
https://github.com/davidcr01/WordlePlus/assets/72193239/326b659a-c65d-480f-9e0b-6a3b45adb384
Description
As an administrator, is necessary to implement the logic of creating new participations for a tournament. This consists in assigning players to a tournament.
Tasks