|
| 1 | +from typing import NamedTuple |
| 2 | + |
1 | 3 | from django.db import models |
2 | 4 | from django.db.models import Func, Value, Count, Q |
3 | 5 | from django.db.models.functions import Replace |
|
9 | 11 | ) |
10 | 12 |
|
11 | 13 |
|
| 14 | +class HeaderVersionData(NamedTuple): |
| 15 | + """Consolidated data needed to render the navbar version dropdown.""" |
| 16 | + |
| 17 | + options: list |
| 18 | + most_recent: "Version | None" # noqa: F821 |
| 19 | + most_recent_beta: "Version | None" # noqa: F821 |
| 20 | + |
| 21 | + |
12 | 22 | class VersionQuerySet(models.QuerySet): |
13 | 23 | def active(self): |
14 | 24 | """Return active versions""" |
@@ -166,6 +176,49 @@ def should_show_beta(most_recent_beta): |
166 | 176 |
|
167 | 177 | return queryset.order_by(order_by) |
168 | 178 |
|
| 179 | + def get_header_dropdown_data(self) -> HeaderVersionData: |
| 180 | + """Single-query fetch for the navbar version dropdown. |
| 181 | +
|
| 182 | + Replaces the 3-4 queries from calling `most_recent()`, |
| 183 | + `most_recent_beta()`, and `get_dropdown_versions()` separately. Dropdown |
| 184 | + list matches `get_dropdown_versions()` for the header's use case only — |
| 185 | + no develop/master, no library filtering. |
| 186 | + """ |
| 187 | + name_exclusions = [ |
| 188 | + "head", |
| 189 | + MASTER_RELEASE_URL_PATH_STR, |
| 190 | + DEVELOP_RELEASE_URL_PATH_STR, |
| 191 | + ] |
| 192 | + versions = list( |
| 193 | + self.active() |
| 194 | + .filter(Q(full_release=True) | Q(beta=True)) |
| 195 | + .exclude(name__in=name_exclusions) |
| 196 | + .defer("data") |
| 197 | + .order_by("-name") |
| 198 | + ) |
| 199 | + |
| 200 | + most_recent = next((v for v in versions if not v.beta and v.full_release), None) |
| 201 | + most_recent_beta = next((v for v in versions if v.beta), None) |
| 202 | + |
| 203 | + include_beta = ( |
| 204 | + most_recent_beta is not None |
| 205 | + and most_recent is not None |
| 206 | + and most_recent_beta.cleaned_version_parts |
| 207 | + > most_recent.cleaned_version_parts |
| 208 | + ) |
| 209 | + if include_beta: |
| 210 | + options = [ |
| 211 | + v for v in versions if not v.beta or v.name == most_recent_beta.name |
| 212 | + ] |
| 213 | + else: |
| 214 | + options = [v for v in versions if not v.beta] |
| 215 | + |
| 216 | + return HeaderVersionData( |
| 217 | + options=options, |
| 218 | + most_recent=most_recent, |
| 219 | + most_recent_beta=most_recent_beta, |
| 220 | + ) |
| 221 | + |
169 | 222 |
|
170 | 223 | class VersionFileQuerySet(models.QuerySet): |
171 | 224 | def active(self): |
|
0 commit comments