recommendationList.py 3.35 KB
Newer Older
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
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,
    IsFollower,
    ReadOnly,
    IsPublic,
)
from base_app.models import User


class RecommendationList(BaseModel):
    moderation_level = 0

    last_update = models.DateTimeField(auto_now=True)
    title = models.CharField(max_length=200)
    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)
    universities = models.ManyToManyField(University)


class RecommendationListSerializer(BaseModelSerializer):
    last_update = serializers.DateTimeField(read_only=True)
    universities = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
    is_user_owner = serializers.SerializerMethodField()
    nb_followers = serializers.SerializerMethodField()

    def get_is_user_owner(self, obj):
        return self.get_user_from_request().pk == obj.owner.pk

    def get_nb_followers(self, obj):
        if obj.is_public:
            return obj.followers.count()
        else:
            return 0

    def do_before_save(self):
        """
        For safety: enforce (for sure) that we update the model corresponding to the user/owner.
        """
        super().do_before_save()

        user = self.get_user_from_request()

        self.override_validated_data({"owner": user})

    class Meta:
        model = RecommendationList
        fields = BaseModelSerializer.Meta.fields + (
            "title",
            "owner",
            "is_public",
            "nb_followers",
            "description",
            "content",
            "is_user_owner",
            "universities",
            "last_update",
        )


class RecommendationListSerializerShort(RecommendationListSerializer):
    class Meta:
        model = RecommendationList
        fields = BaseModelSerializer.Meta.fields + (
            "title",
            "owner",
            "is_public",
            "nb_followers",
            "is_user_owner",
            "description",
        )


class RecommendationListViewSet(BaseModelViewSet):
    serializer_class = RecommendationListSerializer
    end_point_route = "recommendationLists"
    permission_classes = (IsOwner | (IsFollower & 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)