@@ -159,13 +159,13 @@ def get_queryset(self):
159159 "exploits" ,
160160 Prefetch (
161161 "affecting_packages" ,
162- queryset = models .Vulnerability .objects .only (
162+ queryset = models .Package .objects .only (
163163 "type" , "namespace" , "name" , "version"
164164 ),
165165 ),
166166 Prefetch (
167167 "fixed_by_packages" ,
168- queryset = models .Vulnerability .objects .only (
168+ queryset = models .Package .objects .only (
169169 "type" , "namespace" , "name" , "version"
170170 ),
171171 ),
@@ -185,68 +185,22 @@ def get_context_data(self, **kwargs):
185185 weakness_object for weakness_object in vulnerability .weaknesses .all ()
186186 if weakness_object .weakness
187187 ]
188-
189- # Cache aggregated packages
190- (
191- sorted_fixed_by_packages ,
192- sorted_affected_packages ,
193- all_affected_fixed_by_matches ,
194- ) = vulnerability .aggregate_fixed_and_affected_packages ()
195-
196- severity_vectors , severity_values = self .get_severity_vectors_and_values (vulnerability )
197188
198189 context .update (
199190 {
200191 "vulnerability" : vulnerability ,
201192 "vulnerability_search_form" : VulnerabilitySearchForm (self .request .GET ),
202193 "severities" : list (vulnerability .severities .all ()),
203194 "severity_score_range" : "" ,
204- "severity_vectors" : severity_vectors ,
205195 "references" : list (vulnerability .references .all ()),
206196 "aliases" : list (vulnerability .aliases .all ()),
207- "affected_packages" : sorted_affected_packages ,
208- "fixed_by_packages" : sorted_fixed_by_packages ,
209197 "weaknesses" : weaknesses_present_in_db ,
210198 "status" : vulnerability .get_status_label ,
211199 "history" : vulnerability .history ,
212- "all_affected_fixed_by_matches" : all_affected_fixed_by_matches ,
213200 }
214201 )
215202 return context
216203
217- def get_severity_vectors_and_values (self , vulnerability ):
218- """
219- Collect severity vectors and values, excluding EPSS scoring systems efficiently.
220- """
221- severity_vectors = []
222- severity_values = set ()
223-
224- # Use prefetch data if available
225- valid_scoring_severities = getattr (vulnerability , "prefetched_valid_severities" , [])
226-
227- for severity in valid_scoring_severities :
228- try :
229- vector_values = SCORING_SYSTEMS [severity .scoring_system ].get (
230- severity .scoring_elements
231- )
232- if vector_values :
233- severity_vectors .append (vector_values )
234- except (
235- CVSS2MalformedError ,
236- CVSS3MalformedError ,
237- CVSS4MalformedError ,
238- NotImplementedError ,
239- ) as e :
240- logging .error (f"CVSSMalformedError for { severity .scoring_elements } : { e } " )
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- )
246-
247- return severity_vectors , severity_values
248-
249-
250204class HomePage (View ):
251205 template_name = "index.html"
252206
@@ -314,3 +268,52 @@ def form_valid(self, form):
314268
315269 def get_success_url (self ):
316270 return reverse_lazy ("api_user_request" )
271+
272+
273+ class VulnerabilityPackagesDetails (DetailView ):
274+ """
275+ View to display all packages affected by or fixing a specific vulnerability.
276+ URL: /vulnerabilities/{vulnerability_id}/packages
277+ """
278+
279+ model = models .Vulnerability
280+ template_name = "vulnerability_package_details.html"
281+ slug_url_kwarg = "vulnerability_id"
282+ slug_field = "vulnerability_id"
283+
284+ def get_queryset (self ):
285+ """
286+ Prefetch and optimize related data to minimize database hits.
287+ """
288+ return super ().get_queryset ().prefetch_related (
289+ Prefetch (
290+ "affecting_packages" ,
291+ queryset = models .Package .objects .only (
292+ "type" , "namespace" , "name" , "version"
293+ ),
294+ ),
295+ Prefetch (
296+ "fixed_by_packages" ,
297+ queryset = models .Package .objects .only (
298+ "type" , "namespace" , "name" , "version"
299+ ),
300+ ),
301+ )
302+
303+ def get_context_data (self , ** kwargs ):
304+ """
305+ Build context with preloaded QuerySets and minimize redundant queries.
306+ """
307+ context = super ().get_context_data (** kwargs )
308+ vulnerability = self .object
309+ (
310+ sorted_fixed_by_packages ,
311+ sorted_affected_packages ,
312+ all_affected_fixed_by_matches ,
313+ ) = vulnerability .aggregate_fixed_and_affected_packages ()
314+ context .update ({
315+ "affected_packages" : sorted_affected_packages ,
316+ "fixed_by_packages" : sorted_fixed_by_packages ,
317+ "all_affected_fixed_by_matches" : all_affected_fixed_by_matches ,
318+ })
319+ return context
0 commit comments