Skip to content

Commit

Permalink
Merge pull request #35 from PROCOLLAB-github/dev
Browse files Browse the repository at this point in the history
added /projects/count/; /projects/ now only shows not drafted projects
  • Loading branch information
Yakser authored Nov 16, 2022
2 parents b12c466 + e28ced1 commit 01ba218
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 29 deletions.
63 changes: 35 additions & 28 deletions projects/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,48 @@

class ProjectManager(Manager):
def get_projects_for_list_view(self):
return self.get_queryset().prefetch_related(
Prefetch(
"industry",
queryset=Industry.objects.only("name").all(),
),
Prefetch(
"leader",
queryset=CustomUser.objects.only("id").all(),
),
# Prefetch(
# "collaborator_set",
# queryset=Collaborator.objects.filter(
# id__in=Subquery(
# Collaborator.objects
# .filter(project_id=OuterRef('project_id')).values_list('id', flat=True)[:4]
# )
# ),
# to_attr='collaborators'
# ),
# Yes, this fetches the entire collaborator_set even though we only need 4 and the total count.
# No, You can't do it any other way than this.
# Above is a hack that can fetch max 4 vacancies, but if you use it the count will always be <=4.
# To get the count right using the thing above you either have to make another godawful hack,
# Or override the default QuerySet to always ask the DB only count after all the filters.
# (ticket referring to the reason why you can't
# prefetch N items easily https://code.djangoproject.com/ticket/26780)
# (seems like in django 4.2.0 it'll be fixed but at the time of writing the latest version is 4.1.3
Prefetch("collaborator_set"),
return (
self.get_queryset()
.filter(draft=False)
.prefetch_related(
Prefetch(
"industry",
queryset=Industry.objects.only("name").all(),
),
Prefetch(
"leader",
queryset=CustomUser.objects.only("id").all(),
),
# Prefetch(
# "collaborator_set",
# queryset=Collaborator.objects.filter(
# id__in=Subquery(
# Collaborator.objects
# .filter(project_id=OuterRef('project_id')).values_list('id', flat=True)[:4]
# )
# ),
# to_attr='collaborators'
# ),
# Yes, this fetches the entire collaborator_set even though we only need 4 and the total count.
# No, You can't do it any other way than this.
# Above is a hack that can fetch max 4 vacancies, but if you use it the count will always be <=4.
# To get the count right using the thing above you either have to make another godawful hack,
# Or override the default QuerySet to always ask the DB only count after all the filters.
# (ticket referring to the reason why you can't
# prefetch N items easily https://code.djangoproject.com/ticket/26780)
# (seems like in django 4.2.0 it'll be fixed but at the time of writing the latest version is 4.1.3
Prefetch("collaborator_set"),
)
)

def get_projects_for_detail_view(self):
return (
self.get_queryset().prefetch_related("achievements", "collaborator_set").all()
)

def get_projects_for_count_view(self):
return self.get_queryset().filter(draft=False).only("id")

def check_if_owns_any_projects(self, user) -> bool:
# I don't think this should work but the function has no usages, so I'll let it be
return user.leader_projects.exists()
Expand Down
2 changes: 2 additions & 0 deletions projects/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
AchievementList,
AchievementDetail,
ProjectCollaborators,
ProjectCountView,
)

app_name = "projects"
Expand All @@ -16,6 +17,7 @@
path("", ProjectList.as_view()),
path("<int:pk>/collaborators", ProjectCollaborators.as_view()),
path("<int:pk>/", ProjectDetail.as_view()),
path("count/", ProjectCountView.as_view()),
path("steps/", ProjectSteps.as_view()),
path("achievements/", AchievementList.as_view()),
path("achievements/<int:pk>/", AchievementDetail.as_view()),
Expand Down
13 changes: 12 additions & 1 deletion projects/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django_filters import rest_framework as filters
from rest_framework import generics, permissions
from rest_framework import generics, permissions, status
from rest_framework.response import Response
from rest_framework.views import APIView

Expand Down Expand Up @@ -73,6 +73,17 @@ class ProjectDetail(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [IsProjectLeaderOrReadOnly]


class ProjectCountView(generics.GenericAPIView):
queryset = Project.objects.get_projects_for_count_view()
serializer_class = ProjectListSerializer
# TODO: using this permission could result in a user not having verified email
# creating a project; probably should make IsUserVerifiedOrReadOnly
permission_classes = [permissions.IsAuthenticatedOrReadOnly]

def get(self, request):
return Response({"count": self.get_queryset().count()}, status=status.HTTP_200_OK)


class ProjectCollaborators(generics.GenericAPIView):
"""
Project collaborator retrieve/add/delete view
Expand Down

0 comments on commit 01ba218

Please sign in to comment.