File tree Expand file tree Collapse file tree 3 files changed +46
-2
lines changed Expand file tree Collapse file tree 3 files changed +46
-2
lines changed Original file line number Diff line number Diff line change @@ -207,6 +207,9 @@ class Meta:
207
207
unique_together = [("project" , "slug" )]
208
208
ordering = ["-verbose_name" ]
209
209
210
+ # Property used for prefetching version related fields
211
+ LATEST_BUILD_CACHE = "_latest_build"
212
+
210
213
def __str__ (self ):
211
214
return self .verbose_name
212
215
@@ -291,6 +294,19 @@ def vcs_url(self):
291
294
292
295
@property
293
296
def last_build (self ):
297
+ # TODO deprecated in favor of `latest_build`, which matches naming on
298
+ # the Project model
299
+ return self .latest_build
300
+
301
+ @property
302
+ def latest_build (self ):
303
+ # Check if there is `_latest_build` prefetch in the Queryset.
304
+ # Used for database optimization.
305
+ if hasattr (self , self .LATEST_BUILD_CACHE ):
306
+ if latest_build := getattr (self , self .LATEST_BUILD_CACHE ):
307
+ return latest_build [0 ]
308
+ return None
309
+
294
310
return self .builds .order_by ("-date" ).first ()
295
311
296
312
@property
Original file line number Diff line number Diff line change 3
3
4
4
import structlog
5
5
from django .db import models
6
- from django .db .models import Q
6
+ from django .db .models import OuterRef , Prefetch , Q , Subquery
7
7
from django .utils import timezone
8
8
9
9
from readthedocs .builds .constants import (
@@ -141,6 +141,30 @@ def for_reindex(self):
141
141
.distinct ()
142
142
)
143
143
144
+ def prefetch_subquery (self ):
145
+ """
146
+ Prefetch related objects via subquery for each version.
147
+
148
+ .. note::
149
+
150
+ This should come after any filtering.
151
+ """
152
+ from readthedocs .builds .models import Build
153
+
154
+ # Prefetch the latest build for each project.
155
+ subquery_builds = Subquery (
156
+ Build .internal .filter (version = OuterRef ("version_id" ))
157
+ .order_by ("-date" )
158
+ .values_list ("id" , flat = True )[:1 ]
159
+ )
160
+ prefetch_builds = Prefetch (
161
+ "builds" ,
162
+ Build .internal .filter (pk__in = subquery_builds ),
163
+ to_attr = self .model .LATEST_BUILD_CACHE ,
164
+ )
165
+
166
+ return self .prefetch_related (prefetch_builds )
167
+
144
168
145
169
class VersionQuerySet (SettingsOverrideObject ):
146
170
_default_class = VersionQuerySetBase
Original file line number Diff line number Diff line change @@ -123,7 +123,11 @@ def get_context_data(self, **kwargs):
123
123
queryset = versions ,
124
124
project = project ,
125
125
)
126
- versions = self .get_filtered_queryset ()
126
+ versions = (
127
+ self .get_filtered_queryset ()
128
+ .prefetch_related ("project" )
129
+ .prefetch_subquery ()
130
+ )
127
131
context ["versions" ] = versions
128
132
129
133
protocol = "http"
You can’t perform that action at this time.
0 commit comments