From 1518f39900a37f80d09ab23269c32c160ff813f5 Mon Sep 17 00:00:00 2001 From: denis_shtanskii Date: Mon, 4 Nov 2024 00:04:58 +0300 Subject: [PATCH] =?UTF-8?q?refactor:=20=D0=94=D0=BE=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B0=D0=BB=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=BB=D1=8F=20=D0=B2=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D1=8C=D1=86=D0=B0=20=D0=B8=D0=BB=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D1=83=D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0,=20=D0=B4=D0=BB=D1=8F=20=D0=B7=D0=B0=D1=8F=D0=B2?= =?UTF-8?q?=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/api/v1/general/views.py | 2 +- src/backend/api/v1/profile/serializers.py | 2 +- src/backend/api/v1/projects/serializers.py | 6 +-- src/backend/api/v1/projects/views.py | 50 ++++++++++++++-------- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/backend/api/v1/general/views.py b/src/backend/api/v1/general/views.py index 7ddc179..d84f9fd 100644 --- a/src/backend/api/v1/general/views.py +++ b/src/backend/api/v1/general/views.py @@ -29,7 +29,7 @@ class CounterApiView(generics.RetrieveAPIView): """Представление счетчика проектов и пользователей.""" @method_decorator(cache_page(600)) - def get(self, request): + def get(self, request) -> Response: with connection.cursor() as cursor: cursor.execute( """ diff --git a/src/backend/api/v1/profile/serializers.py b/src/backend/api/v1/profile/serializers.py index 11107c7..0781e5d 100644 --- a/src/backend/api/v1/profile/serializers.py +++ b/src/backend/api/v1/profile/serializers.py @@ -150,7 +150,7 @@ class Meta(BaseProfileSerializer.Meta): ) read_only_fields = fields - def get_is_favorite(self, profile): + def get_is_favorite(self, profile) -> bool: user = self.context["request"].user return ( user.is_authenticated diff --git a/src/backend/api/v1/projects/serializers.py b/src/backend/api/v1/projects/serializers.py index 05792ee..3be5c02 100644 --- a/src/backend/api/v1/projects/serializers.py +++ b/src/backend/api/v1/projects/serializers.py @@ -161,7 +161,7 @@ def get_is_favorite(self, project) -> bool: return project.favorited_by.filter(id=user.id).exists() return False - def get_owner(self, project): + def get_owner(self, project) -> dict[str, Any]: """Метод возвращает требуемые поля для владельца.""" owner = project.owner return { @@ -173,7 +173,7 @@ def get_owner(self, project): "visible_status": owner.profile.visible_status, } - def get_unique_project_participants_skills(self, obj): + def get_unique_project_participants_skills(self, obj) -> list[Any]: all_skills = chain.from_iterable( [ participant.skills.values_list("name", flat=True) @@ -368,7 +368,7 @@ class Meta: "project", ) - def get_position(self, obj): + def get_position(self, obj) -> str: """Метод получения specialization из ProfessionSerializer.""" return ProfessionSerializer(obj.position.profession).data[ "specialization" diff --git a/src/backend/api/v1/projects/views.py b/src/backend/api/v1/projects/views.py index 7551b43..de2268f 100644 --- a/src/backend/api/v1/projects/views.py +++ b/src/backend/api/v1/projects/views.py @@ -1,8 +1,14 @@ +from django.contrib.auth.base_user import AbstractBaseUser from django.contrib.auth.models import AnonymousUser from django.db.models import Prefetch, Q, QuerySet +from django.db.models.manager import BaseManager from django.shortcuts import get_object_or_404 from django_filters.rest_framework import DjangoFilterBackend -from drf_spectacular.utils import extend_schema, extend_schema_view +from drf_spectacular.utils import ( + OpenApiParameter, + extend_schema, + extend_schema_view, +) from rest_framework import mixins, status from rest_framework.decorators import action from rest_framework.permissions import SAFE_METHODS, AllowAny, IsAuthenticated @@ -282,6 +288,20 @@ class ProjectSpecialistsViewSet( @extend_schema_view( retrieve=extend_schema(exclude=True), + list=extend_schema( + parameters=[ + OpenApiParameter( + "role", + type=str, + description="Роль пользователя: owner или participant", + required=True, + enum=[ + "owner", + "participant", + ], # Ограничение на допустимые значения + ) + ] + ), ) class ProjectParticipationRequestsViewSet(ModelViewSet): """Представление для запросов на участие в проекте.""" @@ -297,6 +317,8 @@ class ProjectParticipationRequestsViewSet(ModelViewSet): def get_queryset(self) -> QuerySet["ParticipationRequest"]: """Метод получения queryset-а для запросов на участие в проекте.""" + user = self.request.user + role = self.request.query_params.get("role") queryset = ( super() .get_queryset() @@ -312,12 +334,10 @@ def get_queryset(self) -> QuerySet["ParticipationRequest"]: ).prefetch_related( "project__directions", ) - user = self.request.user - if ( - queryset.filter(project__owner=user).exists() - or queryset.filter(project__creator=user).exists() - ): - queryset = queryset.exclude( + if role == "owner": + queryset = queryset.filter( + Q(project__owner=user) | Q(project__creator=user) + ).exclude( request_status__in=[ RequestStatuses.ACCEPTED, RequestStatuses.REJECTED, @@ -325,7 +345,7 @@ def get_queryset(self) -> QuerySet["ParticipationRequest"]: ) queryset.filter(is_viewed=False).update(is_viewed=True) return queryset - return queryset.filter(Q(user=self.request.user)).only( + return queryset.filter(Q(user=user)).only( *PROJECT_PARTICIPATION_REQUEST_ONLY_FIELDS.get(self.action, ()) ) @@ -351,13 +371,9 @@ def get_queryset(self) -> QuerySet["ParticipationRequest"]: def get_serializer_class(self) -> type[BaseSerializer]: """Метод получения сериализатора для запросов на участие в проекте.""" - - is_owner = any( - self.request.user in (pr.project.owner, pr.project.creator) - for pr in self.get_queryset() - ) + role = self.request.query_params.get("role") if self.request.method in SAFE_METHODS: - if is_owner: + if role == "owner": return ReadListParticipationRequestSerializer return MyRequestsSerializer return WriteParticipationRequestSerializer @@ -384,7 +400,7 @@ def answer(self, request, pk) -> Response: """Метод ответа на запрос на участие в проекте.""" participation_request = self.get_object() - serializer = self.serializer_class( + serializer = self.get_serializer( instance=participation_request, data=request.data, context=self.get_serializer_context(), @@ -401,8 +417,8 @@ class InvitationToProjectViewSet(ModelViewSet): http_method_names = ("get", "post", "patch", "delete", "options") permission_classes = (IsInvitationAuthorOrUser,) - def get_queryset(self): - user = self.request.user + def get_queryset(self) -> BaseManager[InvitationToProject]: + user: AbstractBaseUser | AnonymousUser = self.request.user return ( InvitationToProject.objects.filter(Q(user=user) | Q(author=user)) .order_by("-created")