Skip to content

Commit

Permalink
add prefetch and select related
Browse files Browse the repository at this point in the history
  • Loading branch information
samonaisi committed Nov 25, 2024
1 parent 5c7d451 commit f0c45ce
Show file tree
Hide file tree
Showing 16 changed files with 86 additions and 124 deletions.
62 changes: 29 additions & 33 deletions apps/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ def get_full_name(self) -> str:
def get_project_queryset(self) -> QuerySet["Project"]:
if self._project_queryset is None:
if self.is_superuser:
self._project_queryset = Project.objects.all().distinct()
self._project_queryset = Project.objects.all()
else:
public_projects = Project.objects.filter(
publication_status=Project.PublicationStatus.PUBLIC
Expand All @@ -531,12 +531,10 @@ def get_project_queryset(self) -> QuerySet["Project"]:
.union(org_user_projects)
.union(org_admin_projects)
)
self._project_queryset = Project.objects.filter(
id__in=qs.values("id")
).distinct()
return self._project_queryset
self._project_queryset = Project.objects.filter(id__in=qs.values("id"))
return self._project_queryset.distinct()

def get_news_queryset(self, *prefetch) -> QuerySet["News"]:
def get_news_queryset(self) -> QuerySet["News"]:
if self._news_queryset is None:
if self.is_superuser:
self._news_queryset = News.objects.all()
Expand All @@ -552,9 +550,9 @@ def get_news_queryset(self, *prefetch) -> QuerySet["News"]:
& Q(visible_by_all=False)
)
)
return self._news_queryset.distinct().prefetch_related(*prefetch)
return self._news_queryset.distinct()

def get_instruction_queryset(self, *prefetch) -> QuerySet["Instruction"]:
def get_instruction_queryset(self) -> QuerySet["Instruction"]:
if self._instruction_queryset is None:
if self.is_superuser:
self._instruction_queryset = Instruction.objects.all()
Expand All @@ -570,9 +568,9 @@ def get_instruction_queryset(self, *prefetch) -> QuerySet["Instruction"]:
& Q(visible_by_all=False)
)
)
return self._instruction_queryset.distinct().prefetch_related(*prefetch)
return self._instruction_queryset.distinct()

def get_event_queryset(self, *prefetch) -> QuerySet["Event"]:
def get_event_queryset(self) -> QuerySet["Event"]:
if self._event_queryset is None:
if self.is_superuser:
self._event_queryset = Event.objects.all()
Expand All @@ -588,12 +586,12 @@ def get_event_queryset(self, *prefetch) -> QuerySet["Event"]:
& Q(visible_by_all=False)
)
)
return self._event_queryset.distinct().prefetch_related(*prefetch)
return self._event_queryset.distinct()

def get_user_queryset(self, *prefetch) -> QuerySet["ProjectUser"]:
def get_user_queryset(self) -> QuerySet["ProjectUser"]:
if self._user_queryset is None:
if self.is_superuser:
self._user_queryset = ProjectUser.objects.all().distinct()
self._user_queryset = ProjectUser.objects.all()
else:
request_user = ProjectUser.objects.filter(id=self.id)
public_users = ProjectUser.objects.filter(
Expand All @@ -615,15 +613,13 @@ def get_user_queryset(self, *prefetch) -> QuerySet["ProjectUser"]:
.union(org_user_users)
.union(org_admin_users)
)
self._user_queryset = ProjectUser.objects.filter(
id__in=qs.values("id")
).distinct()
return self._user_queryset.prefetch_related(*prefetch)
self._user_queryset = ProjectUser.objects.filter(id__in=qs.values("id"))
return self._user_queryset.distinct()

def get_people_group_queryset(self, *prefetch) -> QuerySet["PeopleGroup"]:
def get_people_group_queryset(self) -> QuerySet["PeopleGroup"]:
if self._people_group_queryset is None:
if self.is_superuser:
self._people_group_queryset = PeopleGroup.objects.all().distinct()
self._people_group_queryset = PeopleGroup.objects.all()
else:
public_groups = PeopleGroup.objects.filter(
publication_status=PeopleGroup.PublicationStatus.PUBLIC
Expand All @@ -647,8 +643,8 @@ def get_people_group_queryset(self, *prefetch) -> QuerySet["PeopleGroup"]:
)
self._people_group_queryset = PeopleGroup.objects.filter(
id__in=qs.values("id")
).distinct()
return self._people_group_queryset.prefetch_related(*prefetch)
)
return self._people_group_queryset.distinct()

def get_project_related_queryset(
self, queryset: QuerySet, project_related_name: str = "project"
Expand Down Expand Up @@ -963,52 +959,52 @@ def get_project_queryset(self) -> QuerySet["Project"]:
if self._project_queryset is None:
self._project_queryset = Project.objects.filter(
publication_status=Project.PublicationStatus.PUBLIC
).distinct()
return self._project_queryset.prefetch_related()
)
return self._project_queryset.distinct()

def get_news_queryset(self, *prefetch) -> QuerySet["News"]:
def get_news_queryset(self) -> QuerySet["News"]:
if self._news_queryset is None:
self._news_queryset = News.objects.filter(
Q(visible_by_all=True)
| Q(
people_groups__publication_status=PeopleGroup.PublicationStatus.PUBLIC
)
)
return self._news_queryset.distinct().prefetch_related(*prefetch)
return self._news_queryset.distinct()

def get_event_queryset(self, *prefetch) -> QuerySet["Event"]:
def get_event_queryset(self) -> QuerySet["Event"]:
if self._event_queryset is None:
self._event_queryset = Event.objects.filter(
Q(visible_by_all=True)
| Q(
people_groups__publication_status=PeopleGroup.PublicationStatus.PUBLIC
)
)
return self._event_queryset.distinct().prefetch_related(*prefetch)
return self._event_queryset.distinct()

def get_instruction_queryset(self, *prefetch) -> QuerySet["Instruction"]:
def get_instruction_queryset(self) -> QuerySet["Instruction"]:
if self._instruction_queryset is None:
self._instruction_queryset = Instruction.objects.filter(
Q(visible_by_all=True)
| Q(
people_groups__publication_status=PeopleGroup.PublicationStatus.PUBLIC
)
)
return self._instruction_queryset.distinct().prefetch_related(*prefetch)
return self._instruction_queryset.distinct()

def get_user_queryset(self, *prefetch) -> QuerySet["ProjectUser"]:
def get_user_queryset(self) -> QuerySet["ProjectUser"]:
if self._user_queryset is None:
self._user_queryset = ProjectUser.objects.filter(
privacy_settings__publication_status=PrivacySettings.PrivacyChoices.PUBLIC
)
return self._user_queryset.prefetch_related(*prefetch)
return self._user_queryset.distinct()

def get_people_group_queryset(self, *prefetch) -> QuerySet["PeopleGroup"]:
def get_people_group_queryset(self) -> QuerySet["PeopleGroup"]:
if self._people_group_queryset is None:
self._people_group_queryset = PeopleGroup.objects.filter(
publication_status=PeopleGroup.PublicationStatus.PUBLIC
)
return self._people_group_queryset.prefetch_related(*prefetch)
return self._people_group_queryset.distinct()

def get_project_related_queryset(
self, queryset: QuerySet, project_related_name: str = "project"
Expand Down
18 changes: 13 additions & 5 deletions apps/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from apps.organizations.permissions import HasOrganizationPermission
from apps.projects.models import Project
from apps.projects.serializers import ProjectLightSerializer
from apps.skills.models import Skill
from keycloak import (
KeycloakDeleteError,
KeycloakGetError,
Expand Down Expand Up @@ -172,8 +173,11 @@ def get_queryset(self):
queryset = self.annotate_organization_role(queryset, organization)
if self.action == "admin_list":
queryset = self.annotate_keycloak_email_verified(queryset)
skills_prefetch = Prefetch(
"skills", queryset=Skill.objects.select_related("tag")
)
return queryset.prefetch_related(
"skills__tag",
skills_prefetch,
"groups",
)

Expand Down Expand Up @@ -528,10 +532,14 @@ def get_permissions(self):

def get_queryset(self) -> QuerySet:
if "organization_code" in self.kwargs:
return self.request.user.get_people_group_queryset().filter(
organization__code=self.kwargs["organization_code"],
is_root=False,
).prefetch_related("organization")
return (
self.request.user.get_people_group_queryset()
.filter(
organization__code=self.kwargs["organization_code"],
is_root=False,
)
.select_related("organization")
)
return PeopleGroup.objects.none()

def get_serializer_class(self):
Expand Down
20 changes: 0 additions & 20 deletions apps/announcements/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,13 @@
)
from apps.files.serializers import ImageSerializer
from apps.organizations.models import Organization
from apps.organizations.serializers import (
OrganizationLightSerializer,
OrganizationSerializer,
ProjectCategorySerializer,
)
from apps.projects.models import Project
from apps.projects.utils import get_views_from_serializer

from .models import Announcement


class ProjectAnnouncementSerializer(serializers.ModelSerializer):
categories = ProjectCategorySerializer(many=True, read_only=True)
header_image = ImageSerializer(read_only=True)
organizations = OrganizationSerializer(many=True, read_only=True)
views = serializers.SerializerMethodField()

class Meta:
model = Project
Expand All @@ -34,15 +25,10 @@ class Meta:
"slug",
"purpose",
"publication_status",
"categories",
"header_image",
"language",
"organizations",
"views",
]

get_views = get_views_from_serializer


class AnnouncementSerializer(
OrganizationRelatedSerializer, ProjectRelatedSerializer, serializers.ModelSerializer
Expand Down Expand Up @@ -70,12 +56,6 @@ class Meta:
"project_id",
]

def get_organizations(self, announcement: Announcement) -> dict:
organizations = OrganizationLightSerializer(
announcement.project.organizations, many=True
)
return organizations.data

def get_related_organizations(self) -> List[Organization]:
"""Retrieve the related organizations"""
if "organizations" in self.validated_data:
Expand Down
2 changes: 1 addition & 1 deletion apps/feedbacks/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def get_queryset(self) -> QuerySet:
Q(reply_on__isnull=False)
| (Q(deleted_at__isnull=False) & Q(replies=None))
)
return qs.select_related("author").prefetch_related("replies")
return qs.select_related("author")

def create(self, request, *args, **kwargs):
get_object_or_404(
Expand Down
3 changes: 1 addition & 2 deletions apps/notifications/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,14 @@
class NotificationsViewSet(ListViewSet):
"""Allows getting or modifying a user's notification."""

queryset = Notification.objects.all()
permission_classes = [ReadOnly]
serializer_class = NotificationsSerializer

def get_queryset(self):
return (
Notification.objects.filter(receiver=self.request.user)
.order_by("-created")
.select_related("sender", "project")
.select_related("sender", "project", "organization")
)

@transaction.atomic
Expand Down
21 changes: 0 additions & 21 deletions apps/organizations/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,24 +560,3 @@ def update(
instance.template.save()
validated_data.pop("template")
return super().update(instance, validated_data)


class ProjectCategoryLightSerializer(OrganizationRelatedSerializer):
projects_count = serializers.SerializerMethodField()

class Meta:
model = ProjectCategory
fields = [
"id",
"name",
"background_color",
"foreground_color",
"projects_count",
]

def get_projects_count(self, obj: ProjectCategory) -> int:
return obj.projects.count()

def get_related_organizations(self) -> List[Organization]:
self.is_valid(raise_exception=True)
return [ProjectCategory.objects.get(id=self.validated_data["id"]).organization]
18 changes: 7 additions & 11 deletions apps/organizations/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,15 @@ class ProjectCategoryViewSet(viewsets.ModelViewSet):
serializer_class = ProjectCategorySerializer
filterset_class = ProjectCategoryFilter
organization_code_lookup = "organization__code"
queryset = ProjectCategory.objects.select_related(
"organization", "template"
).prefetch_related("tags")
lookup_field = "id"
lookup_value_regex = "[0-9]+"

def get_queryset(self):
return super().get_queryset().filter(is_root=False)
return (
ProjectCategory.objects.filter(is_root=False)
.select_related("organization")
.prefetch_related("tags")
)

def get_permissions(self):
codename = map_action_to_permission(self.action, "projectcategory")
Expand Down Expand Up @@ -145,12 +146,7 @@ class OrganizationViewSet(viewsets.ModelViewSet):
filter_backends = [DjangoFilterBackend]
filterset_class = OrganizationFilter
organization_code_lookup = "code"
queryset = Organization.objects.select_related(
"faq", "parent", "banner_image", "logo_image"
).prefetch_related(
"default_skills_tags",
"default_projects_tags",
)
queryset = Organization.objects.all()
lookup_field = "code"
lookup_value_regex = "[a-zA-Z0-9_-]+"

Expand Down Expand Up @@ -365,7 +361,7 @@ def get_queryset(self):
if "organization_code" in self.kwargs:
return Faq.objects.filter(
organization__code=self.kwargs["organization_code"]
).prefetch_related("images")
)
return Faq.objects.none()

def get_object(self):
Expand Down
2 changes: 0 additions & 2 deletions apps/projects/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,6 @@ class ProjectMessageSerializer(serializers.ModelSerializer):
)

# read_only
project = serializers.PrimaryKeyRelatedField(read_only=True)
author = UserLighterSerializer(read_only=True)
replies = RecursiveField(read_only=True, many=True)
images = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
Expand All @@ -825,7 +824,6 @@ class Meta:
"deleted_at",
"reply_on",
# read only
"project",
"author",
"replies",
"images",
Expand Down
8 changes: 4 additions & 4 deletions apps/projects/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,8 +464,8 @@ class BlogEntryViewSet(MultipleIDViewsetMixin, viewsets.ModelViewSet):
def get_queryset(self) -> QuerySet:
if "project_id" in self.kwargs:
return self.request.user.get_project_related_queryset(
BlogEntry.objects.filter(project=self.kwargs["project_id"]),
).prefetch_related("images")
BlogEntry.objects.filter(project=self.kwargs["project_id"])
)
return BlogEntry.objects.none()

def perform_create(self, serializer):
Expand Down Expand Up @@ -750,8 +750,8 @@ def get_queryset(self):
# get_project_related_queryset is not needed because the publication_status is not checked here
queryset = ProjectMessage.objects.filter(project=self.kwargs["project_id"])
if self.action in ["retrieve", "list"]:
return queryset.exclude(reply_on__isnull=False)
return queryset
queryset = queryset.exclude(reply_on__isnull=False)
return queryset.select_related("author")
return ProjectMessage.objects.none()

def perform_create(self, serializer):
Expand Down
4 changes: 3 additions & 1 deletion apps/search/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@


class ProjectSearchSerializer(serializers.ModelSerializer):
categories = serializers.SlugRelatedField(many=True, read_only=True, slug_field="name")
categories = serializers.SlugRelatedField(
many=True, read_only=True, slug_field="name"
)
header_image = ImageSerializer(read_only=True)
is_followed = serializers.SerializerMethodField(read_only=True)

Expand Down
Loading

0 comments on commit f0c45ce

Please sign in to comment.