Coverage for api\serializers\evenement.py: 70%

44 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-10-13 15:18 +0200

1""" 

2Module contenant le sérialiseur pour le modèle Evenement. 

3 

4Ce module définit la sérialisation/désérialisation des données des événements 

5sportifs pour l'API REST, incluant la gestion des relations avec les épreuves et lieux. 

6""" 

7from rest_framework import serializers 

8from api.models import Evenement, Lieu, Epreuve 

9from api.serializers.lieu import LieuSerializer 

10from api.serializers.epreuve import EpreuveSerializer 

11 

12 

13class EvenementSerializer(serializers.ModelSerializer): 

14 """ 

15 Sérialiseur pour le modèle Evenement. 

16 

17 Gère la sérialisation des événements avec leurs relations aux épreuves et lieux. 

18 Permet l'assignation d'épreuves à un événement tout en évitant les conflits. 

19 

20 :ivar epreuves: Liste des épreuves associées (lecture seule) 

21 :type epreuves: list of EpreuveSerializer 

22 :ivar epreuve_ids: IDs des épreuves à associer (écriture seule) 

23 :type epreuve_ids: PrimaryKeyRelatedField 

24 :ivar lieu: Données complètes du lieu (lecture seule) 

25 :type lieu: LieuSerializer 

26 :ivar lieu_id: ID du lieu pour l'écriture 

27 :type lieu_id: PrimaryKeyRelatedField 

28 """ 

29 epreuves = EpreuveSerializer(many=True, read_only=True) 

30 epreuve_ids = serializers.PrimaryKeyRelatedField( 

31 queryset=Epreuve.objects.all(), 

32 many=True, 

33 write_only=True, 

34 source='epreuves', 

35 required=False 

36 ) 

37 lieu = LieuSerializer(read_only=True) 

38 lieu_id = serializers.PrimaryKeyRelatedField( 

39 queryset=Lieu.objects.all(), 

40 write_only=True, 

41 source='lieu' 

42 ) 

43 

44 class Meta: 

45 """ 

46 Configuration du sérialiseur. 

47 

48 :cvar model: Modèle Django associé au sérialiseur 

49 :type model: Evenement 

50 :cvar fields: Champs inclus dans la sérialisation 

51 :type fields: list 

52 """ 

53 model = Evenement 

54 fields = [ 

55 'id', 'description', 

56 'lieu', 'lieu_id', 

57 'date', 'horraire', 

58 'epreuves', 'epreuve_ids', 

59 'nb_place_total', 'nb_place_restante' 

60 ] 

61 

62 def validate_epreuve_ids(self, value): 

63 """ 

64 Valide les IDs des épreuves à associer à l'événement. 

65 

66 Vérifie qu'aucune épreuve n'est déjà assignée à un autre événement 

67 pour éviter les conflits d'assignation. 

68 

69 :param value: Liste des épreuves à valider 

70 :type value: list of Epreuve 

71 :return: Liste des épreuves validées 

72 :rtype: list of Epreuve 

73 :raises serializers.ValidationError: Si des épreuves sont déjà assignées ailleurs 

74 """ 

75 if not value: 

76 return value 

77 

78 # Vérifier les conflits en excluant l'événement actuel (si modification) 

79 instance_id = self.instance.id if self.instance else None 

80 conflits = [] 

81 

82 for epreuve in value: 

83 if epreuve.evenement_id is not None and epreuve.evenement_id != instance_id: 

84 conflits.append(epreuve) 

85 

86 if conflits: 

87 raise serializers.ValidationError( 

88 f"Les épreuves suivantes sont déjà assignées à d'autres événements : {[e.id for e in conflits]}" 

89 ) 

90 return value 

91 

92 def create(self, validated_data): 

93 """ 

94 Crée un nouvel événement avec ses épreuves associées. 

95 

96 :param validated_data: Données validées pour la création 

97 :type validated_data: dict 

98 :return: L'événement créé avec ses épreuves assignées 

99 :rtype: Evenement 

100 """ 

101 epreuves = validated_data.pop('epreuves', []) 

102 evenement = Evenement.objects.create(**validated_data) 

103 

104 for epreuve in epreuves: 

105 epreuve.evenement = evenement 

106 epreuve.save() 

107 

108 return evenement 

109 

110 def update(self, instance, validated_data): 

111 """ 

112 Met à jour un événement et gère les épreuves associées. 

113 

114 Désassocie les anciennes épreuves et assigne les nouvelles si présentes. 

115 

116 :return: L'événement mis à jour 

117 """ 

118 epreuves = validated_data.pop('epreuves', None) 

119 

120 for attr, value in validated_data.items(): 

121 setattr(instance, attr, value) 

122 instance.save() 

123 

124 if epreuves is not None: 

125 nouveaux_ids = {e.pk for e in epreuves} 

126 anciens_ids = set(instance.epreuves.values_list('id', flat=True)) 

127 

128 # Désassocier les épreuves qui ne sont plus dans la liste 

129 instance.epreuves.filter(id__in=anciens_ids - nouveaux_ids).update(evenement=None) 

130 

131 # Associer les nouvelles épreuves 

132 for epreuve in epreuves: 

133 if epreuve.pk not in anciens_ids: 

134 epreuve.evenement = instance 

135 epreuve.save() 

136 

137 return instance