Skip to content

Commit ed9dc63

Browse files
committed
part II of 37e69f6 - split Album.bmanager prefetches and annotations into seperate methods, tests are still WIP
1 parent ea23804 commit ed9dc63

File tree

5 files changed

+35
-32
lines changed

5 files changed

+35
-32
lines changed

src/albums/api.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def album_create(request: HttpRequest, payload: AlbumRequestSchema) -> AlbumApiR
7171
# assign permissions and return response
7272
album.add_initial_permissions()
7373
# get from database so the bmanager is used
74-
album = Album.bmanager.get(pk=album.pk)
74+
album = Album.bmanager.prefetch_active_files_list().get(pk=album.pk)
7575
return 201, {"bma_response": album}
7676

7777

@@ -83,7 +83,7 @@ def album_create(request: HttpRequest, payload: AlbumRequestSchema) -> AlbumApiR
8383
)
8484
def album_get(request: HttpRequest, album_uuid: uuid.UUID) -> AlbumApiResponseType:
8585
"""Return an album."""
86-
album = get_object_or_404(Album.bmanager.all(), uuid=album_uuid)
86+
album = get_object_or_404(Album.bmanager.annotate_memberships().prefetch_active_files_list().all(), uuid=album_uuid)
8787
return 200, {"bma_response": album}
8888

8989

@@ -95,7 +95,7 @@ def album_get(request: HttpRequest, album_uuid: uuid.UUID) -> AlbumApiResponseTy
9595
)
9696
def album_list(request: HttpRequest, filters: AlbumFilters = query) -> AlbumApiResponseType:
9797
"""Return a list of albums."""
98-
albums = Album.bmanager.all()
98+
albums = Album.bmanager.annotate_memberships().prefetch_active_files_list().all()
9999

100100
if filters.files:
101101
# __in is OR and we want AND, build a query for .exclude() with all file UUIDs
@@ -154,7 +154,7 @@ def album_update(
154154
check: bool = False,
155155
) -> AlbumApiResponseType:
156156
"""Update (PATCH) or replace (PUT) an Album."""
157-
album = get_object_or_404(Album.bmanager.all(), uuid=album_uuid)
157+
album = get_object_or_404(Album.bmanager.prefetch_active_files_list().all(), uuid=album_uuid)
158158
if not request.user.has_perm("change_album", album):
159159
# no permission
160160
return 403, {"message": "Permission denied."}

src/albums/managers.py

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,7 @@ class AlbumManager(models.Manager): # type: ignore[type-arg]
1818

1919
def get_queryset(self): # type: ignore[no-untyped-def] # noqa: ANN201
2020
"""Annotations and prefetches for the Album model."""
21-
qs = super().get_queryset()
22-
23-
# queries to count past, present, and future memberships of each album
24-
active_memberships = Count("memberships", filter=Q(memberships__period__contains=timezone.now()), distinct=True)
25-
historic_memberships = Count("memberships", filter=Q(memberships__period__endswith__lt=timezone.now()))
26-
future_memberships = Count("memberships", filter=Q(memberships__period__startswith__gt=timezone.now()))
27-
28-
return (
29-
qs.annotate(
30-
active_memberships=active_memberships,
31-
historic_memberships=historic_memberships,
32-
future_memberships=future_memberships,
33-
)
34-
.select_related("owner")
35-
.prefetch_related("user_permissions__user")
36-
.prefetch_related("user_permissions__permission")
37-
.prefetch_related("group_permissions__group")
38-
.prefetch_related("group_permissions__permission")
39-
.prefetch_related("hits")
40-
.annotate(hitcount=Count("hits", distinct=True))
41-
.prefetch_active_files_list(recursive=True)
42-
# ordering from Album META gets lost for some reason :(
43-
).order_by("created_at")
44-
21+
return super().get_queryset()
4522

4623
class AlbumQuerySet(models.QuerySet): # type: ignore[type-arg]
4724
"""Custom queryset for album operations."""
@@ -76,3 +53,30 @@ def prefetch_active_files_list(self, *, recursive: bool = True) -> models.QueryS
7653
to_attr="active_files_list",
7754
),
7855
)
56+
57+
def prefetch_user_permissions(self) -> models.QuerySet["Album"]:
58+
"""Prefetch user permissions."""
59+
return self.prefetch_related("user_permissions__user").prefetch_related("user_permissions__permission")
60+
61+
def prefetch_group_permissions(self) -> models.QuerySet["Album"]:
62+
"""Prefetch group permissions."""
63+
return self.prefetch_related("group_permissions__group").prefetch_related("group_permissions__permission")
64+
65+
def annotate_hitcount(self) -> models.QuerySet["Album"]:
66+
"""Annotate hitcounts for the qs."""
67+
return self.annotate(hitcount=Count("hits", distinct=True))
68+
69+
def annotate_memberships(self) -> models.QuerySet["Album"]:
70+
"""Annotate membership counts."""
71+
active_memberships = Count("memberships", filter=Q(memberships__period__contains=timezone.now()), distinct=True)
72+
historic_memberships = Count("memberships", filter=Q(memberships__period__endswith__lt=timezone.now()))
73+
future_memberships = Count("memberships", filter=Q(memberships__period__startswith__gt=timezone.now()))
74+
return self.annotate(
75+
active_memberships=active_memberships,
76+
historic_memberships=historic_memberships,
77+
future_memberships=future_memberships,
78+
)
79+
80+
def select_owner(self) -> models.QuerySet["Album"]:
81+
"""Get owner with select_related()."""
82+
return self.select_related("owner")

src/albums/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class AlbumListView(SingleTableMixin, FilterView):
4848

4949
def get_queryset(self) -> models.QuerySet[Album]:
5050
"""Use bmanager to get rich album objects."""
51-
return Album.bmanager.all()
51+
return Album.bmanager.annotate_memberships().annotate_hitcount().all()
5252

5353

5454
class AlbumDetailView(SingleTableMixin, FilterView):
@@ -64,7 +64,7 @@ def get_template_names(self) -> list[str]:
6464

6565
def get_object(self, queryset: models.QuerySet[Album] | None = None) -> Album:
6666
"""Use the manager so the album object has prefetched active_files."""
67-
album = Album.bmanager.get(pk=self.kwargs["album_uuid"])
67+
album = Album.bmanager.prefetch_active_files_list().get(pk=self.kwargs["album_uuid"])
6868
# count the hit
6969
count_hit(self.request, album)
7070
return album # type: ignore[no-any-return]

src/files/tables.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class FileTable(tables.Table):
4343

4444
# only show on 5xl and up
4545
tags = BPColumn(bp="5xl", verbose_name="Tags")
46-
hitcount = BPColumn(bp="5xl", verbose_name="Hits")
46+
hitcount = BPColumn(bp="5xl", verbose_name="Hits", orderable=False)
4747

4848
# only show on 6xl and up
4949
jobs = BPColumn(bp="6xl", verbose_name="Jobs", order_by="jobs_finished")

src/jobs/tables.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ class JobTable(tables.Table):
1919
basefile = tables.Column(verbose_name="File", linkify=True)
2020
job_type = tables.Column(verbose_name="Job Type", orderable=False)
2121
result_url = tables.Column(verbose_name="Result url", orderable=False)
22-
2322
# show only at xxl and up
2423
width = BPColumn(bp="xxl", orderable=False)
2524
height = BPColumn(bp="xxl", orderable=False)

0 commit comments

Comments
 (0)