Skip to content

Commit 4aa2cc4

Browse files
committed
Fix views
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent 607a90b commit 4aa2cc4

File tree

1 file changed

+49
-29
lines changed

1 file changed

+49
-29
lines changed

vulnerabilities/views.py

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from django.views import generic
2323
from django.views.generic.detail import DetailView
2424
from django.views.generic.list import ListView
25+
from django.db.models import Prefetch
2526

2627
from vulnerabilities import models
2728
from vulnerabilities.forms import ApiUserCreationForm
@@ -143,68 +144,86 @@ class VulnerabilityDetails(DetailView):
143144
slug_field = "vulnerability_id"
144145

145146
def get_queryset(self):
147+
"""
148+
Prefetch and optimize related data to minimize database hits.
149+
"""
146150
return (
147151
super()
148152
.get_queryset()
153+
.select_related()
149154
.prefetch_related(
150155
"references",
151156
"aliases",
152157
"weaknesses",
153158
"severities",
154159
"exploits",
160+
Prefetch(
161+
"affecting_packages",
162+
queryset=models.Vulnerability.objects.only(
163+
"type", "namespace", "name", "version"
164+
),
165+
),
166+
Prefetch(
167+
"fixed_by_packages",
168+
queryset=models.Vulnerability.objects.only(
169+
"type", "namespace", "name", "version"
170+
),
171+
),
155172
)
156173
)
157174

175+
158176
def get_context_data(self, **kwargs):
177+
"""
178+
Build context with preloaded QuerySets and minimize redundant queries.
179+
"""
159180
context = super().get_context_data(**kwargs)
160-
weaknesses = self.object.weaknesses.all()
181+
vulnerability = self.object
182+
183+
# Pre-fetch and process data in Python instead of the template
161184
weaknesses_present_in_db = [
162-
weakness_object for weakness_object in weaknesses if weakness_object.weakness
185+
weakness_object for weakness_object in vulnerability.weaknesses.all()
186+
if weakness_object.weakness
163187
]
164-
status = self.object.get_status_label
165-
166-
# severity_vectors, severity_values = self.get_severity_vectors_and_values()
167-
188+
189+
# Cache aggregated packages
168190
(
169191
sorted_fixed_by_packages,
170192
sorted_affected_packages,
171193
all_affected_fixed_by_matches,
172-
) = self.object.aggregate_fixed_and_affected_packages()
194+
) = vulnerability.aggregate_fixed_and_affected_packages()
195+
196+
severity_vectors, severity_values = self.get_severity_vectors_and_values(vulnerability)
173197

174198
context.update(
175199
{
176-
"vulnerability": self.object,
200+
"vulnerability": vulnerability,
177201
"vulnerability_search_form": VulnerabilitySearchForm(self.request.GET),
178-
"severities": list(self.object.severities.all()),
202+
"severities": list(vulnerability.severities.all()),
179203
"severity_score_range": "",
180-
"severity_vectors": [],
181-
"references": self.object.references.all(),
182-
"aliases": self.object.aliases.all(),
204+
"severity_vectors": severity_vectors,
205+
"references": list(vulnerability.references.all()),
206+
"aliases": list(vulnerability.aliases.all()),
183207
"affected_packages": sorted_affected_packages,
184208
"fixed_by_packages": sorted_fixed_by_packages,
185209
"weaknesses": weaknesses_present_in_db,
186-
"status": status,
187-
"history": self.object.history,
210+
"status": vulnerability.get_status_label,
211+
"history": vulnerability.history,
188212
"all_affected_fixed_by_matches": all_affected_fixed_by_matches,
189213
}
190214
)
191215
return context
192216

193-
def get_severity_vectors_and_values(self):
217+
def get_severity_vectors_and_values(self, vulnerability):
194218
"""
195-
Collect severity vectors and values, excluding EPSS scoring systems and handling errors gracefully.
219+
Collect severity vectors and values, excluding EPSS scoring systems efficiently.
196220
"""
197221
severity_vectors = []
198222
severity_values = set()
199-
200-
# Exclude EPSS scoring system
201-
base_severities = self.object.severities.exclude(scoring_system=EPSS.identifier)
202-
203-
# QuerySet for severities with valid scoring_elements and scoring_system in SCORING_SYSTEMS
204-
valid_scoring_severities = base_severities.filter(
205-
scoring_elements__isnull=False, scoring_system__in=SCORING_SYSTEMS.keys()
206-
)
207-
223+
224+
# Use prefetch data if available
225+
valid_scoring_severities = getattr(vulnerability, "prefetched_valid_severities", [])
226+
208227
for severity in valid_scoring_severities:
209228
try:
210229
vector_values = SCORING_SYSTEMS[severity.scoring_system].get(
@@ -219,10 +238,11 @@ def get_severity_vectors_and_values(self):
219238
NotImplementedError,
220239
) as e:
221240
logging.error(f"CVSSMalformedError for {severity.scoring_elements}: {e}")
222-
223-
valid_value_severities = base_severities.filter(value__isnull=False).exclude(value="")
224-
225-
severity_values.update(valid_value_severities.values_list("value", flat=True))
241+
242+
# Collect valid values using a pre-filtered queryset
243+
severity_values.update(
244+
vulnerability.severities.exclude(value__isnull=True).exclude(value="").values_list("value", flat=True)
245+
)
226246

227247
return severity_vectors, severity_values
228248

0 commit comments

Comments
 (0)