Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

from django.db import models 

from django.db.models import Q 

from rest_framework import serializers 

 

from backend_app.fields import JSONField 

from backend_app.models.abstract.base import ( 

BaseModel, 

BaseModelSerializer, 

BaseModelViewSet, 

) 

from backend_app.models.university import University 

from backend_app.permissions.app_permissions import IsOwner, ReadOnly, IsPublic 

from backend_app.permissions.moderation import ModerationLevels 

from backend_app.validation.validators import ( 

RecommendationListJsonContentValidator, 

RecommendationListUnivValidator, 

) 

from base_app.models import User 

 

json_content_validator = RecommendationListJsonContentValidator() 

univ_content_validator = RecommendationListUnivValidator() 

 

 

class RecommendationList(BaseModel): 

moderation_level = ModerationLevels.NO_MODERATION 

 

last_update = models.DateTimeField(auto_now=True) 

title = models.CharField(max_length=100) 

owner = models.ForeignKey( 

User, on_delete=models.CASCADE, related_name="user_recommendation_list" 

) 

 

is_public = models.BooleanField(default=False) 

followers = models.ManyToManyField( 

User, related_name="followed_recommendation_list" 

) 

description = models.CharField(max_length=300, default="") 

content = JSONField( 

default=list, validators=[json_content_validator, univ_content_validator] 

) 

universities = models.ManyToManyField(University) 

 

def save(self, *args, **kwargs): 

""" 

Custom save function to ensure consistency. 

Won't be active on first create 

""" 

# Will crash if pk is None 

if self.pk is not None: 

self.universities.clear() 

univ_ids_in_list = RecommendationListUnivValidator.get_universities_ids_from_content( 

self.content 

) 

for univ in University.objects.all(): 

if univ.pk in univ_ids_in_list: 

self.universities.add(univ) 

 

return super().save(*args, **kwargs) 

 

 

class RecommendationListSerializer(BaseModelSerializer): 

last_update = serializers.DateTimeField(read_only=True) 

universities = serializers.PrimaryKeyRelatedField(read_only=True, many=True) 

is_user_owner = serializers.SerializerMethodField() 

is_user_follower = serializers.SerializerMethodField() 

nb_followers = serializers.SerializerMethodField() 

owner_pseudo = serializers.SerializerMethodField() 

 

def get_is_user_owner(self, obj): 

return self.get_user_from_request().pk == obj.owner.pk 

 

def get_is_user_follower(self, obj): 

if obj.pk is None: 

return False 

else: 

return obj.followers.filter(pk=self.get_user_from_request().pk).exists() 

 

def get_nb_followers(self, obj): 

if obj.is_public: 

return obj.followers.count() 

else: 

return 0 

 

def get_owner_pseudo(self, obj): 

return obj.owner.pseudo 

 

def create(self, validated_data): 

# make sure we cannot create list for others 

validated_data["owner"] = self.get_user_from_request() 

return super().create(validated_data) 

 

class Meta: 

model = RecommendationList 

fields = BaseModelSerializer.Meta.fields + ( 

"title", 

"owner", 

"is_public", 

"nb_followers", 

"description", 

"content", 

"is_user_owner", 

"is_user_follower", 

"universities", 

"last_update", 

"owner_pseudo", 

) 

 

 

class RecommendationListSerializerShort(RecommendationListSerializer): 

class Meta: 

model = RecommendationList 

fields = BaseModelSerializer.Meta.fields + ( 

"title", 

"owner", 

"is_public", 

"nb_followers", 

"is_user_owner", 

"description", 

"last_update", 

"owner_pseudo", 

) 

 

 

class RecommendationListViewSet(BaseModelViewSet): 

serializer_class = RecommendationListSerializer 

end_point_route = "recommendationLists" 

permission_classes = (IsOwner | (IsPublic & ReadOnly),) 

 

def get_serializer_class(self): 

if "action" in self.__dict__ and self.action == "list": 

return RecommendationListSerializerShort 

else: 

return RecommendationListSerializer 

 

def get_queryset(self): # this functions allows to get the user's lists 

owned = Q(owner=self.request.user) 

followed = Q(followers__in=[self.request.user], is_public=True) 

query = owned | followed 

 

if "action" in self.__dict__ and self.action != "list": 

is_public = Q(is_public=True) 

query = query | is_public 

 

return RecommendationList.objects.filter(query).prefetch_related( 

"owner", "universities" 

)