@@ -431,6 +431,9 @@ class ExtraDataFieldMixin(models.Model):
431431 help_text = _ ("Optional mapping of extra data key/values." ),
432432 )
433433
434+ class Meta :
435+ abstract = True
436+
434437 def update_extra_data (self , data ):
435438 """Update the `extra_data` field with the provided `data` dict."""
436439 if not isinstance (data , dict ):
@@ -439,9 +442,6 @@ def update_extra_data(self, data):
439442 self .extra_data .update (data )
440443 self .save (update_fields = ["extra_data" ])
441444
442- class Meta :
443- abstract = True
444-
445445
446446class UpdateMixin :
447447 """
@@ -635,6 +635,10 @@ def save(self, *args, **kwargs):
635635 if global_webhook and is_new and not is_clone and not skip_global_webhook :
636636 self .setup_global_webhook ()
637637
638+ def get_absolute_url (self ):
639+ """Return this project's details URL."""
640+ return reverse ("project_detail" , args = [self .slug ])
641+
638642 def setup_global_webhook (self ):
639643 """
640644 Create a global webhook subscription instance from values defined in the
@@ -1428,10 +1432,6 @@ def add_error(
14281432 object_instance ,
14291433 )
14301434
1431- def get_absolute_url (self ):
1432- """Return this project's details URL."""
1433- return reverse ("project_detail" , args = [self .slug ])
1434-
14351435 @cached_property
14361436 def resource_count (self ):
14371437 """Return the number of resources related to this project."""
@@ -2533,21 +2533,6 @@ class Compliance(models.TextChoices):
25332533 class Meta :
25342534 abstract = True
25352535
2536- @classmethod
2537- def from_db (cls , db , field_names , values ):
2538- """
2539- Store the ``license_expression_field`` on loading this instance from the
2540- database value.
2541- The cached value is then used to detect changes on `save()`.
2542- """
2543- new = super ().from_db (db , field_names , values )
2544-
2545- if cls .license_expression_field in field_names :
2546- field_index = field_names .index (cls .license_expression_field )
2547- new ._loaded_license_expression = values [field_index ]
2548-
2549- return new
2550-
25512536 def save (self , codebase = None , * args , ** kwargs ):
25522537 """
25532538 Injects policies, if the feature is enabled, when the
@@ -2566,6 +2551,21 @@ def save(self, codebase=None, *args, **kwargs):
25662551
25672552 super ().save (* args , ** kwargs )
25682553
2554+ @classmethod
2555+ def from_db (cls , db , field_names , values ):
2556+ """
2557+ Store the ``license_expression_field`` on loading this instance from the
2558+ database value.
2559+ The cached value is then used to detect changes on `save()`.
2560+ """
2561+ new = super ().from_db (db , field_names , values )
2562+
2563+ if cls .license_expression_field in field_names :
2564+ field_index = field_names .index (cls .license_expression_field )
2565+ new ._loaded_license_expression = values [field_index ]
2566+
2567+ return new
2568+
25692569 @property
25702570 def policy_index (self ):
25712571 return self .project .policy_index
@@ -2790,6 +2790,9 @@ class Meta:
27902790 def __str__ (self ):
27912791 return self .path
27922792
2793+ def get_absolute_url (self ):
2794+ return reverse ("resource_detail" , args = [self .project .slug , self .path ])
2795+
27932796 @property
27942797 def location_path (self ):
27952798 """Return the location of the resource as a Path instance."""
@@ -2949,9 +2952,6 @@ def extracted_from(self, codebase=None):
29492952 archive_path , _ , _ = self .path .rpartition ("-extract" )
29502953 return self .project .get_resource (archive_path )
29512954
2952- def get_absolute_url (self ):
2953- return reverse ("resource_detail" , args = [self .project .slug , self .path ])
2954-
29552955 def get_raw_url (self ):
29562956 """Return the URL to access the RAW content of the resource."""
29572957 return reverse ("resource_raw" , args = [self .project .slug , self .path ])
@@ -3143,14 +3143,14 @@ class VulnerabilityMixin(models.Model):
31433143
31443144 affected_by_vulnerabilities = models .JSONField (blank = True , default = list )
31453145
3146+ class Meta :
3147+ abstract = True
3148+
31463149 @property
31473150 def is_vulnerable (self ):
31483151 """Returns True if this instance is affected by vulnerabilities."""
31493152 return bool (self .affected_by_vulnerabilities )
31503153
3151- class Meta :
3152- abstract = True
3153-
31543154
31553155class VulnerabilityQuerySetMixin :
31563156 def vulnerable (self ):
0 commit comments