2222from django .views import generic
2323from django .views .generic .detail import DetailView
2424from django .views .generic .list import ListView
25+ from django .db .models import Prefetch
2526
2627from vulnerabilities import models
2728from 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