Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions projects/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
User = get_user_model()


class EmptySerializer(serializers.Serializer):
pass


class AchievementListSerializer(serializers.ModelSerializer):
class Meta:
model = Achievement
Expand Down Expand Up @@ -115,23 +119,34 @@ class Meta:
fields = ("id", "first_name", "last_name", "avatar")


class ProjectGoalBulkListSerializer(serializers.ListSerializer):
"""Bulk_create при POST запросе со списком объектов на /projects/{project_pk}/goals/."""

def create(self, validated_data):
project = self.context["project"]
objs = [ProjectGoal(project=project, **item) for item in validated_data]
created = ProjectGoal.objects.bulk_create(objs)
return created


class ProjectGoalSerializer(serializers.ModelSerializer):
project = serializers.PrimaryKeyRelatedField(read_only=True)
project_id = serializers.IntegerField(read_only=True)
responsible = serializers.PrimaryKeyRelatedField(queryset=User.objects.all())
responsible_info = ResponsibleMiniSerializer(source="responsible", read_only=True)

class Meta:
model = ProjectGoal
fields = [
"id",
"project",
"project_id",
"title",
"completion_date",
"responsible",
"responsible_info",
"is_done",
]
read_only_fields = ["id", "project", "responsible_info"]
read_only_fields = ["id", "project_id", "responsible_info"]
list_serializer_class = ProjectGoalBulkListSerializer


class ProjectDetailSerializer(serializers.ModelSerializer):
Expand Down
12 changes: 8 additions & 4 deletions projects/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@
)

app_name = "projects"
project_goal_list = GoalViewSet.as_view({"get": "list", "post": "create"})
project_goal_list = GoalViewSet.as_view(
{
"get": "list",
"post": "create",
}
)

project_goal_detail = GoalViewSet.as_view(
{
"get": "retrieve",
Expand Down Expand Up @@ -55,9 +61,7 @@
),
path("<int:pk>/", ProjectDetail.as_view()),
path("<int:pk>/recommended_users", ProjectRecommendedUsers.as_view()),
path(
"assign-to-program/", DuplicateProjectView.as_view(), name="duplicate-project"
),
path("assign-to-program/", DuplicateProjectView.as_view(), name="duplicate-project"),
path(
"<int:project_id>/program-fields/",
PartnerProgramFieldValueBulkUpdateView.as_view(),
Expand Down
68 changes: 44 additions & 24 deletions projects/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from projects.serializers import (
AchievementDetailSerializer,
AchievementListSerializer,
EmptySerializer,
ProjectCollaboratorSerializer,
ProjectDetailSerializer,
ProjectDuplicateRequestSerializer,
Expand Down Expand Up @@ -90,9 +91,7 @@ def create(self, request, *args, **kwargs):

try:
partner_program_id = request.data.get("partner_program_id")
update_partner_program(
partner_program_id, request.user, serializer.instance
)
update_partner_program(partner_program_id, request.user, serializer.instance)
except PartnerProgram.DoesNotExist:
return Response(
{"detail": "Partner program with this id does not exist"},
Expand All @@ -105,9 +104,7 @@ def create(self, request, *args, **kwargs):
)

headers = self.get_success_headers(serializer.data)
return Response(
serializer.data, status=status.HTTP_201_CREATED, headers=headers
)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

def post(self, request, *args, **kwargs):
"""
Expand Down Expand Up @@ -241,9 +238,7 @@ def get(self, request):
{
"all": self.get_queryset().filter(draft=False).count(),
"my": self.get_queryset()
.filter(
Q(leader_id=request.user.id) | Q(collaborator__user=request.user)
)
.filter(Q(leader_id=request.user.id) | Q(collaborator__user=request.user))
.distinct()
.count(),
},
Expand Down Expand Up @@ -313,9 +308,7 @@ def _project_data(
return project.id, project.leader.id

@staticmethod
def _collabs_queryset(
project_id: int, requested_id: int, leader_id: int
) -> QuerySet:
def _collabs_queryset(project_id: int, requested_id: int, leader_id: int) -> QuerySet:
return Collaborator.objects.exclude(
user__id=leader_id
).get( # чтоб случайно лидер сам себя не удалил
Expand Down Expand Up @@ -586,9 +579,7 @@ def _project_data(
return project.id, project.leader.id

@staticmethod
def _collabs_queryset(
project_id: int, requested_id: int, leader_id: int
) -> QuerySet:
def _collabs_queryset(project_id: int, requested_id: int, leader_id: int) -> QuerySet:
return Collaborator.objects.exclude(
user__id=leader_id
).get( # чтоб случайно лидер сам себя не удалил
Expand Down Expand Up @@ -626,6 +617,7 @@ def delete(self, request, project_pk: int) -> Response:
class SwitchLeaderRole(generics.GenericAPIView):
permission_classes = [IsProjectLeader]
queryset = Project.objects.all().select_related("leader")
serializer_class = EmptySerializer

@staticmethod
def _get_new_leader(user_id: int, project: Project) -> Collaborator:
Expand Down Expand Up @@ -677,9 +669,7 @@ def post(self, request):
data = serializer.validated_data

original_project = get_object_or_404(Project, id=data["project_id"])
partner_program = get_object_or_404(
PartnerProgram, id=data["partner_program_id"]
)
partner_program = get_object_or_404(PartnerProgram, id=data["partner_program_id"])

with transaction.atomic():
new_project = Project.objects.create(
Expand Down Expand Up @@ -721,16 +711,46 @@ class GoalViewSet(viewsets.ModelViewSet):
permission_classes = [IsProjectLeaderOrReadOnly]

def get_queryset(self):
qs = super().get_queryset()
project_pk = self.kwargs.get("project_pk")
qs = super().get_queryset()
return qs.filter(project_id=project_pk) if project_pk is not None else qs

def perform_create(self, serializer):
def get_serializer_context(self):
ctx = super().get_serializer_context()
project_pk = self.kwargs.get("project_pk")
if project_pk is None:
serializer.save()
else:
serializer.save(project_id=project_pk)
if project_pk and "project" not in ctx:
ctx["project"] = get_object_or_404(Project, pk=project_pk)
return ctx

@swagger_auto_schema(
request_body=ProjectGoalSerializer(many=True),
responses={201: ProjectGoalSerializer(many=True)},
)
def create(self, request, *args, **kwargs):
if not isinstance(request.data, list):
return Response(
{"detail": "В теле запроса должен быть массив целей."}, status=400
)
serializer = self.get_serializer(data=request.data, many=True)
serializer.is_valid(raise_exception=True)
created = serializer.save()
out = self.get_serializer(created, many=True)
return Response(out.data, status=status.HTTP_201_CREATED)

def update(self, request, *args, **kwargs):
if isinstance(request.data, list):
return Response(
{"detail": "Обновление выполняется для одной цели по её ID."}, status=400
)
return super().update(request, *args, **kwargs)

def partial_update(self, request, *args, **kwargs):
if isinstance(request.data, list):
return Response(
{"detail": "Частичное обновление выполняется для одной цели по её ID."},
status=400,
)
return super().partial_update(request, *args, **kwargs)

def perform_update(self, serializer):
serializer.save(project=self.get_object().project)